Design Pattern
1. Singleton
Giải pháp cho vấn đề tạo duy nhất một thể hiện đối tượng trong hệ thống
2. Builder
Giải pháp cho việc thiết kế một đối tượng có quá nhiều tham số
3. Factory
Giải pháp cho việc tạo một nơi để chuyên khởi tạo đối tượng dựa vào 1 tham số type
--> Mỗi khi có một đối tượng mới, chúng ta cần phải tạo Class đối tượng mới đó và Thêm code trong class Factory để tạo đối tượng mới đó --> bad design
chỉ phù hợp cho một tập hợp nhỏ các đối tượng cần khởi tạo
4. Abstract factory
Giải pháp cho việc tạo ra đối tượng mới,
Việc cần làm là tạo một Class implement AbstractFactory mà tạo ra đối tượng mới đó.
Do đó mỗi khi có đối tượng mới, chúng ta chỉ cần đơn giản là tạo 1 Class về đối tượng đó, và tạo một Class implement AbstractFactoryClass
Do đó chúng ta không phải chỉnh sửa code, mà chỉ thêm mới code vào Source
Great design
5. Proxy
Nó là một thiết kế mà tập trung vào việc truy cập một đối tượng thông qua một Proxy object
6. Strategy
Giải pháp cho việc trừu tượng hóa đối tượng sử dụng
ví dụ chúng ta có một hàm tìm kiếm trừu tượng(InterfaceSearch)
nhưng tìm kiếm điều gì thì cần phải truyền vào Implement của InterfaceSearch đó
ví dụ chúng ta có 1 list Apple có các thuộc tính màu sắc, trọng lượng, thương hiệu, loại , thời gian hái,
Vấn đề là cần phải viết hàm tìm kiếm ra một tập táo có màu sắc là Đỏ
-- Viết 1 hàm findRedApples(List apples): Hàm này thực hiện tìm if(apple.color =="red")
Điều gì nếu hôm sau tôi cần tìm một Set táo có trọng lượng > 3
-- Developer viết thêm một hàm tìm táo findAppleByWeight(List apple, int weight)
....
So confuse
--> giải pháp là Tạo một hàm
mỗi một tiêu chí chúng ta sẽ tạo một Class impl Criteria và thực hiện hàm
Great design: Không phải sửa code hàm findApple, hoặc không phải viết thêm hàm vào 1 class
Chỉ cần tạo một class mới và test Class đó
--> Đảm bảo tính modul đóng gói, không sửa gì có sẵn
7. State design pattern
hãy nghĩ về hàm này
Nhưng điều gì xảy ra nếu TV có thêm một tính năng RESTART
Chúng ta lại phải sửa code hàm controllMyTV check if(state is RESTART) the restart TV
--> Không ổn, lại phải test lại toàn bộ function
---> Giải pháp là tạo 1 interface cho State và một hàm action()
Khi đó hàm controllMyTV sẽ sửa lại như sau
Như vậy mỗi một State chúng ta sẽ implement 1 class cho nó --> đảm bảo việc thêm mới Class thay vì sửa Class--> đảm bảo tính module đóng gói không sửa lại code
8. Visitor
Khi chúng ta có một Interface Item và một tập các sản phẩm đã impl Item
Vd: Máy giặt, máy hút bụi, nồi cơm điện ,....
Vấn đề là khi siêu thị có các chương trình giảm giá tạm gọi là
Chương trình Tết: Giảm 50% Cho các mặt hàng điện thoại, 10% cho các mặt hàng gia dụng
Vậy chúng ta sẽ thiết kế hàm tính giá thế nào cho mỗi sản phẩm
---> Giải pháp là dùng Visitor Design pattern
interface ChuongTrinhVisitor{
double visit(DienThoai item);
double visit(GiaDung item);
}
class ChuongTrinhTetVisitorImpl impl ChuongTrinhVisitor{
double visit( DienThoai item){
if else here and return the price;
}
double visit( GiaDung item){
if else here and return the price;
}
}
----------
interface Item{
double accept(ChuongTrinhVisitor visitor)
}
class DienThoai impl Item{
double accept(ChuongTrinhVisitor visitor){
return visitor.visit(this);
}
}
-------------
using
ChuongTrinhVisitor tet = new ChuongTrìnhTetVisitorImpl();
List<Item> = new ..., list.add ....
Foreach(list) then total += list.get(i).accept(tet)
---------------------------------
Kết luận nếu có thêm một Visitor khác thì chúng ta chỉ việc impl ChuongTrinhVisitor và sử dụng
Nếu có sản phẩm mới thì chỉ việc tạo thêm một sản phẩm và thêm hàm trong các VisitorImpl Tương ứng
---------
Khi thêm sản phẩm mới thì đúng là ác mộng
Dẫn đến cần thiết kế lại :-)))
9. Template
Hiểu đúng theo nghĩa template thì nó là một thứ tự mẫu định sẵn nào đó mà nhiều đối tượng sẽ dùng chung một mẫu
ví dụ như xây một ngôi nhà thì
1. xây nền móng
2. xây trụ
3. xây tường
4. tạo cửa sổ
5. lợp mái
Do vậy các class kế thừa abstract class sẽ ghi đè lại các phương thức và dùng hàm build để thực hiện template đã có sẵn
Là một mẫu thiết kế đúng như tên của nó
Hãy nghĩ về nó như một giải pháp đáp ứng cho Client
Ví dụ một trang trại có nuôi các loài vật sau: Gấu, Thỏ, Đại bàng, Cá
Ông ấy tạo ra các lớp
nếu viết hàm thông thường
thì ông sẽ phải
thay vì viết hàm như vậy
Ông sẽ viết một interface apdapter
Các dùng
Như vậy sau này có thêm các loài khác vào thì chúng ta chỉ cần định nghĩa loài đó rồi sau đó tạo thêm class Adapter cho loài đó là ok. Chúng ta không phải bổ sung hàm trong App class nữa.
--> Đảm bảo tính năng chỉ thêm mới code, không sửa code class có sẵn.
Giải pháp cho vấn đề tạo duy nhất một thể hiện đối tượng trong hệ thống
2. Builder
Giải pháp cho việc thiết kế một đối tượng có quá nhiều tham số
3. Factory
Giải pháp cho việc tạo một nơi để chuyên khởi tạo đối tượng dựa vào 1 tham số type
--> Mỗi khi có một đối tượng mới, chúng ta cần phải tạo Class đối tượng mới đó và Thêm code trong class Factory để tạo đối tượng mới đó --> bad design
chỉ phù hợp cho một tập hợp nhỏ các đối tượng cần khởi tạo
4. Abstract factory
Giải pháp cho việc tạo ra đối tượng mới,
Việc cần làm là tạo một Class implement AbstractFactory mà tạo ra đối tượng mới đó.
Do đó mỗi khi có đối tượng mới, chúng ta chỉ cần đơn giản là tạo 1 Class về đối tượng đó, và tạo một Class implement AbstractFactoryClass
Do đó chúng ta không phải chỉnh sửa code, mà chỉ thêm mới code vào Source
Great design
5. Proxy
Nó là một thiết kế mà tập trung vào việc truy cập một đối tượng thông qua một Proxy object
Interface Image{ showImage() }
RealImage implemnt Image{ construct(){ loadImage() } showImage() }
Proxy impl Image{ RealImage realImg; showImg(){ realImg.showImg() } }
6. Strategy
Giải pháp cho việc trừu tượng hóa đối tượng sử dụng
ví dụ chúng ta có một hàm tìm kiếm trừu tượng(InterfaceSearch)
nhưng tìm kiếm điều gì thì cần phải truyền vào Implement của InterfaceSearch đó
ví dụ chúng ta có 1 list Apple có các thuộc tính màu sắc, trọng lượng, thương hiệu, loại , thời gian hái,
Vấn đề là cần phải viết hàm tìm kiếm ra một tập táo có màu sắc là Đỏ
-- Viết 1 hàm findRedApples(List apples): Hàm này thực hiện tìm if(apple.color =="red")
Điều gì nếu hôm sau tôi cần tìm một Set táo có trọng lượng > 3
-- Developer viết thêm một hàm tìm táo findAppleByWeight(List apple, int weight)
....
So confuse
--> giải pháp là Tạo một hàm
findApple(Criteria criteria){ appleList.forEach( if(apple.check()==true) then add apple to the returnList ) }Criteria là 1 interface có hàm boolean check()
mỗi một tiêu chí chúng ta sẽ tạo một Class impl Criteria và thực hiện hàm
boolean check(Apple apple) { if(apple match criteria) return true; else return false; }theo tiêu chí cần.
Great design: Không phải sửa code hàm findApple, hoặc không phải viết thêm hàm vào 1 class
Chỉ cần tạo một class mới và test Class đó
--> Đảm bảo tính modul đóng gói, không sửa gì có sẵn
7. State design pattern
hãy nghĩ về hàm này
controllMyTV(String state){ if(state is ON) then turn on TV if (state is OFF) the turn off TV }Code chạy khá đẹp
Nhưng điều gì xảy ra nếu TV có thêm một tính năng RESTART
Chúng ta lại phải sửa code hàm controllMyTV check if(state is RESTART) the restart TV
--> Không ổn, lại phải test lại toàn bộ function
---> Giải pháp là tạo 1 interface cho State và một hàm action()
Khi đó hàm controllMyTV sẽ sửa lại như sau
controllMyTV(State state){ state.action(); }
Như vậy mỗi một State chúng ta sẽ implement 1 class cho nó --> đảm bảo việc thêm mới Class thay vì sửa Class--> đảm bảo tính module đóng gói không sửa lại code
8. Visitor
Khi chúng ta có một Interface Item và một tập các sản phẩm đã impl Item
Vd: Máy giặt, máy hút bụi, nồi cơm điện ,....
Vấn đề là khi siêu thị có các chương trình giảm giá tạm gọi là
Chương trình Tết: Giảm 50% Cho các mặt hàng điện thoại, 10% cho các mặt hàng gia dụng
Vậy chúng ta sẽ thiết kế hàm tính giá thế nào cho mỗi sản phẩm
---> Giải pháp là dùng Visitor Design pattern
interface ChuongTrinhVisitor{
double visit(DienThoai item);
double visit(GiaDung item);
}
class ChuongTrinhTetVisitorImpl impl ChuongTrinhVisitor{
double visit( DienThoai item){
if else here and return the price;
}
double visit( GiaDung item){
if else here and return the price;
}
}
----------
interface Item{
double accept(ChuongTrinhVisitor visitor)
}
class DienThoai impl Item{
double accept(ChuongTrinhVisitor visitor){
return visitor.visit(this);
}
}
-------------
using
ChuongTrinhVisitor tet = new ChuongTrìnhTetVisitorImpl();
List<Item> = new ..., list.add ....
Foreach(list) then total += list.get(i).accept(tet)
---------------------------------
Kết luận nếu có thêm một Visitor khác thì chúng ta chỉ việc impl ChuongTrinhVisitor và sử dụng
Nếu có sản phẩm mới thì chỉ việc tạo thêm một sản phẩm và thêm hàm trong các VisitorImpl Tương ứng
---------
Khi thêm sản phẩm mới thì đúng là ác mộng
Dẫn đến cần thiết kế lại :-)))
9. Template
Hiểu đúng theo nghĩa template thì nó là một thứ tự mẫu định sẵn nào đó mà nhiều đối tượng sẽ dùng chung một mẫu
ví dụ như xây một ngôi nhà thì
1. xây nền móng
2. xây trụ
3. xây tường
4. tạo cửa sổ
5. lợp mái
public abstract class HouseTemplate { //template method, final so subclasses can't override public final void buildHouse(){ buildFoundation(); buildPillars(); buildWalls(); buildWindows(); System.out.println("House is built."); } //default implementation private void buildWindows() { System.out.println("Building Glass Windows"); } //methods to be implemented by subclasses public abstract void buildWalls(); public abstract void buildPillars(); private void buildFoundation() { System.out.println("Building foundation with cement,iron rods and sand"); } }
Do vậy các class kế thừa abstract class sẽ ghi đè lại các phương thức và dùng hàm build để thực hiện template đã có sẵn
10. Propotype
Mục đích mẫu thiết kế để tạo ra một Class có khả năng được copy và tạo ra một đối tượng mới có cùng các giá trị thôucj tính
Do vậy chúng ta chỉ cần tạo một class sau đó implement Interface Cloneable
Sau đó impl phương thức clone()
Return Super.clone()
11. Adapter
Là một mẫu thiết kế đúng như tên của nó
Hãy nghĩ về nó như một giải pháp đáp ứng cho Client
Ví dụ một trang trại có nuôi các loài vật sau: Gấu, Thỏ, Đại bàng, Cá
Ông ấy tạo ra các lớp
class Gấu{ int speedDichuyen() }
class Thỏ{ int speedNhảy() }
class DaiBang{ int speedBay() }
class Cá{ int speedBoi() }và ông muốn viết một chương trình để tính tốc độ cho từng loài vật mà ông đang nuôi
nếu viết hàm thông thường
thì ông sẽ phải
class App{ int tinhTocdoTho(Tho tho){ return tho.speedNhay(); } ..... // tương tự các loài khác }như vậy sẽ rất khó cho việc maintain code trong tương lai, vì có thể có nhiều loài vậy mới ra nhập trang trại, và ông sẽ phải sửa lại hàm App và viết thêm function tính tốc độ cho loài đó
thay vì viết hàm như vậy
Ông sẽ viết một interface apdapter
interface AdapterSpeed{ int speed(); }Sau đó ông sẽ viết một class impl cho các loài
class AdapterSpeedTho impl AdapterSpeed{ Tho tho; AdapterSpeedTho(Tho tho); int speed(){ return tho.speedNhay(); } }
Class App{ int tinhTocDo(AdapterSpeed adapter){ adapter.speed(); } }
Các dùng
int speed = App.tinhTocDo( new AdapterSpeedTho(new Tho()));
Như vậy sau này có thêm các loài khác vào thì chúng ta chỉ cần định nghĩa loài đó rồi sau đó tạo thêm class Adapter cho loài đó là ok. Chúng ta không phải bổ sung hàm trong App class nữa.
--> Đảm bảo tính năng chỉ thêm mới code, không sửa code class có sẵn.
12.Facade
Lấy một ví dụ cho dễ hiểu:
Giờ bạn có Một hãng hàng không Bamboo Airway, Vietjet Airway và Vietnam Airline
Nếu bạn muốn bay chuyến VietNam Airline thì cần phải code như sau
Có nghĩa nếu bạn muốn bay một chuyến thì bạn phải biết các hàm trước đó thiết lập trước khi cất cánh fly();
Tuy nhiên là một Client() thì họ sẽ không biết làm thế nào để thực hiện từng bước một và bước nào trước bước nào sau
Facade pattern sinh ra để che giấu đi sự phức tạp đó
Và Client sẽ chỉ dùng cái Facade này để gọi
---> Ok dễ hiểu, design này quá dễ hiểu
13. Composite
Để hiểu về mẫu pattern này thì chúng ta sẽ lấy ví dụ về một Game đua của một tập các động vật
Ví dụ có Ngựa, Trâu, Bò, Thỏ tham gia một cuộc đua
Chúng ta sẽ có một Interface chung
Tại lớp App chúng ta cũng sẽ implement interface trên như sau
Để bắt đầu cuộc đua;
Chúng ta sẽ tạo
Ưu điểm cách thiết kế này là khi có động vật mới thì chúng ta chỉ cần tạo Class động vật đó và Implement Racing interface
Sau đó Client có thể dùng App để add thêm động vật đó vào và tham gia cuộc đua
Việc này lại giúp bảo trì code tốt hơn không chỉnh sửa class đã có mà chỉ việc tạo class mới
14. Flyweight
Về cơ bản mẫu thiết kế này gần giống với mẫu thiết kế Factory pattern
Nhưng khác ở chỗ là mẫu Factory pattern sẽ luôn trả về đối tượng mới dựa trên đối số truyền vào
Còn mẫu Flyweight sẽ lưu ý hơn cho những trường hợp người dùng chỉ muốn tạo mới đối tượng nếu nó không tồn tại và sẽ dùng lại đối tượng cũ nếu nó đã tồn tại
Cơ chế này gần giống như cơ chế cache.
Vậy vấn đề là gì: Mẫu đối tượng cần cache nó phải có những thuộc tính nội tại private mà khi khởi tạo đối tượng chúng ta sẽ setup, và những thuộc tính ngoại tại là cho phép Client setup lại để sử dụng, như vậy thì mẫu này mới có ích. vì việc dùng lại đối tượng đã tạo có thể gặp phải trường hợp là các thuộc tính ngoại tại đã bị thiết lập trước đó.
ví dụ
15. Bridge
Mẫu thiết kế này nó đến như ý nghĩa tên của nó là một cây cầu nối giữa 2 Interface
Từ trước tới giờ chúng ta chủ yếu apply 1 interface như là nhân vật chính cho các mô hình mẫu thiết kế.
nhưng mẫu thiết kế này sẽ đến như là một mô hình mà có 2 nhân vật chính kết hợp với nhau mà một interface sẽ gọi đến hàm một interface khác
16. Object Pool
Chúng ta sẽ tạo một class như Pool là thùng chứa các đối tượng
chúng ta sẽ có 1 list các đối tượng đang sẵn sàng và một list các đối tượng không sẵn sàng
và có cơ chế xóa các đối tượng nếu nó vượt quá thời gian expire, cơ chế này sẽ giúp giảm tài nguyên lưu trữ nếu quá lâu rồi các object trong Pool không được sử dụng, nếu cứ nắm giữ chỗ cho chúng trong Pool thì quả là lãng phí.
Thuật toán getObjectPool như sau
Kiểu tra xem trong availableList có đối tượng Pool không
nếu không có thì tạo mới và put đối tượng vào inUsedList và return obj.
nếu có thì kiểm tra thời gian xem obj đã hết hạn chưa. nếu hết hạn thì remove obj khỏi availableList và tạo obj mới và put và inUsedList
nếu thời gian chưa hết hạn thì dùng luôn và put đối tượng vào inUsedList để giữ object
Hàm releaseObject sẽ thực hiện loại bỏ object khỏi inUsedList và put vào availableList
Lấy một ví dụ cho dễ hiểu:
Giờ bạn có Một hãng hàng không Bamboo Airway, Vietjet Airway và Vietnam Airline
Nếu bạn muốn bay chuyến VietNam Airline thì cần phải code như sau
VietnamAirline flight = new VietnamAirline(); flight.goToPortVietnamAirline(); flight.checkTicket(); flight.fly();Nếu bạn muốn bay Vietjet Air thì
VietjetAir vja= new VietjetAir(); vja.goToPortVietjetAir() vja.fly();
Có nghĩa nếu bạn muốn bay một chuyến thì bạn phải biết các hàm trước đó thiết lập trước khi cất cánh fly();
Tuy nhiên là một Client() thì họ sẽ không biết làm thế nào để thực hiện từng bước một và bước nào trước bước nào sau
Facade pattern sinh ra để che giấu đi sự phức tạp đó
Tạo một class Facade{ flyVietNamAirline(){ //copy các bước trên } flyVietJetAir(){ // copy bên trên các bước vào đây } }
Và Client sẽ chỉ dùng cái Facade này để gọi
---> Ok dễ hiểu, design này quá dễ hiểu
13. Composite
Để hiểu về mẫu pattern này thì chúng ta sẽ lấy ví dụ về một Game đua của một tập các động vật
Ví dụ có Ngựa, Trâu, Bò, Thỏ tham gia một cuộc đua
Chúng ta sẽ có một Interface chung
interface Racing{ void prepare(); // set up time =0; void start(); // set up speed stop(); // caculate running time* speed and update quãng đường đã chạy showQuangDuong(); /// show quãng đường đã chạy }Sau đó chúng ta sẽ implement interface này cho các loài vật trên
class Tho implement Racing, Animal{ int time; int spead; int quangduong; void prepare(); // set up time =0; { time=0; } void start(); // set up speed { speed= 5; } stop(); // caculate running time* speed and update quãng đường đã chạy { quangduong=(System.Time - time)*speed; } showQuangDuong(); /// show quãng đường đã chạy { print(Thỏ đã chạy đương quãng đường: quangduong); } } }
Tại lớp App chúng ta cũng sẽ implement interface trên như sau
class App implement Racing{ List<Animal> animalList = new AninalList() void addToList(Animal animal){ animalList.add(animal); } // remove() void prepare(){ forEach(animalList).each().prepare(); } void start(){ forEach(animalList).each().start(); } void stop(){ forEach(animalList).each().stop(); } void showQuangDuong(){ forEach(animalList).each().showQuangDuong(); } }
Để bắt đầu cuộc đua;
Chúng ta sẽ tạo
App app= new App(); // Tạo động vật tham gia ngựa Animal ngua = new Ngưa(); app.add(ngua) //Tạo thỏ Animal tho= new Tho(); app.add(tho) Tạo trâu Animal trau= new Trau(); app.add(trau) Tạo Bò Animal bo= new Bo(); app.add(bo) // chuẩn bị app.prepare(); //start app.start(); // rung 5s Thread.sleep(5s); //stop app.stop(); //in ra quang duong da chay app.showQuangDuong();Vậy là chúng ta đã thiết kế xong game đua này.
Ưu điểm cách thiết kế này là khi có động vật mới thì chúng ta chỉ cần tạo Class động vật đó và Implement Racing interface
Sau đó Client có thể dùng App để add thêm động vật đó vào và tham gia cuộc đua
Việc này lại giúp bảo trì code tốt hơn không chỉnh sửa class đã có mà chỉ việc tạo class mới
14. Flyweight
Về cơ bản mẫu thiết kế này gần giống với mẫu thiết kế Factory pattern
Nhưng khác ở chỗ là mẫu Factory pattern sẽ luôn trả về đối tượng mới dựa trên đối số truyền vào
Còn mẫu Flyweight sẽ lưu ý hơn cho những trường hợp người dùng chỉ muốn tạo mới đối tượng nếu nó không tồn tại và sẽ dùng lại đối tượng cũ nếu nó đã tồn tại
Cơ chế này gần giống như cơ chế cache.
Vậy vấn đề là gì: Mẫu đối tượng cần cache nó phải có những thuộc tính nội tại private mà khi khởi tạo đối tượng chúng ta sẽ setup, và những thuộc tính ngoại tại là cho phép Client setup lại để sử dụng, như vậy thì mẫu này mới có ích. vì việc dùng lại đối tượng đã tạo có thể gặp phải trường hợp là các thuộc tính ngoại tại đã bị thiết lập trước đó.
ví dụ
public class ShapeFactory { // hashmap dùng để cache dữ liệu các đối tượng đã khởi tạo private static final HashMap<ShapeType,Shape> shapes = new HashMap<ShapeType,Shape>(); public static Shape getShape(ShapeType type) { // lấy từ cache local Shape shapeImpl = shapes.get(type); // nếu không có trong cache if (shapeImpl == null) { if (type.equals(ShapeType.OVAL_FILL)) { } else if (type.equals(ShapeType.OVAL_NOFILL)) { shapeImpl = new Oval(false); } else if (type.equals(ShapeType.LINE)) { shapeImpl = new Line(); } shapes.put(type, shapeImpl); }else{ // nếu có trong cache shapes.reset() // làm mới lại các thuộc tính đã setup trước đó } return shapeImpl; } public static enum ShapeType{ OVAL_FILL,OVAL_NOFILL,LINE; }}
15. Bridge
Mẫu thiết kế này nó đến như ý nghĩa tên của nó là một cây cầu nối giữa 2 Interface
Từ trước tới giờ chúng ta chủ yếu apply 1 interface như là nhân vật chính cho các mô hình mẫu thiết kế.
nhưng mẫu thiết kế này sẽ đến như là một mô hình mà có 2 nhân vật chính kết hợp với nhau mà một interface sẽ gọi đến hàm một interface khác
interface Color(){ void applyColor(); }
class RedColor impl Color(){ void applyColor(){ print("apply redColor"); } }
abstract class Shape{ Color color; // bridge here Shape(Color color){ this.color = color; } abstract void applyColor(Color color); // link to Color's applyColor method }
class Circle extend Shape{ Circle(Color color){ super(color); } void applyColor(Color color){ color.applyColor(); } }Done
16. Object Pool
Chúng ta sẽ tạo một class như Pool là thùng chứa các đối tượng
chúng ta sẽ có 1 list các đối tượng đang sẵn sàng và một list các đối tượng không sẵn sàng
và có cơ chế xóa các đối tượng nếu nó vượt quá thời gian expire, cơ chế này sẽ giúp giảm tài nguyên lưu trữ nếu quá lâu rồi các object trong Pool không được sử dụng, nếu cứ nắm giữ chỗ cho chúng trong Pool thì quả là lãng phí.
Thuật toán getObjectPool như sau
Kiểu tra xem trong availableList có đối tượng Pool không
nếu không có thì tạo mới và put đối tượng vào inUsedList và return obj.
nếu có thì kiểm tra thời gian xem obj đã hết hạn chưa. nếu hết hạn thì remove obj khỏi availableList và tạo obj mới và put và inUsedList
nếu thời gian chưa hết hạn thì dùng luôn và put đối tượng vào inUsedList để giữ object
Hàm releaseObject sẽ thực hiện loại bỏ object khỏi inUsedList và put vào availableList
Comments
Post a Comment