Design pattern trong Java: Abstract Factory

Khái niệm

Abstract Factory là 1 design pattern thuộc loại Creational cho phép bạn tạo ra họ của các class liên quan mà không cần phải chỉ định các class cụ thể của chúng. 

Design pattern Abstract factory

Bài toán?

Hãy tưởng tượng rằng bạn đang tạo một chương trình mô phỏng cửa hàng đồ nội thất. Code của bạn sẽ gồm các class đại diện cho:

  • Một nhóm các sản phẩm liên quan như: Ghế, Sofa, Bàn cafe
  • Một số biến thể của họ các class này. Ví dụ: Các sản phẩm Ghế + Sofa + Bàn cafe có thuộc trong những loại: Hiện đại, cổ điển, quý tộc

Bạn cần một cách để tạo ra các đồ vật nội thất riêng lẻ để chúng phù hợp với các đồ vật khác trong cùng một gia đình. Khách hàng sẽ tức giận nếu như bạn gửi cho họ đồ nội thất không phù hợp.

Ngoài ra, bạn cũng không thể thay đổi cách code hiện có khi thêm sản phẩm mới hoặc nhóm sản phẩm vào chương trình. Các nhà cung cấp đồ nội thất cập nhật danh mục của họ rất thường xuyên và bạn sẽ không muốn thay đổi cấu trúc của code mỗi khi điều đó xảy ra.

Giải pháp

Điều đầu tiên mà Abstract Factory pattern gợi ý là khai báo rõ ràng các interface cho từng sản phẩm riêng biệt của các dòng sản phẩm (Ví dụ: ghế, sofa hoặc bàn cafe).  Sau đó, bạn có thể làm cho tất cả các biến thể của sản phẩm tuân theo interface đó.

Tất cả biến thể của cùng đối tượng phải được chuyển đến một hệ thống phân lớp duy nhất

Bước tiếp theo là khai báo Abstract Factory – một interface với danh sách các function cho tất cả sản phẩm thuộc cùng một họ (ví dụ: createChair(), createSofa(), createCoffeeTable(),…). Các phương thức này phải trả về các loại sản phẩm trừu tượng được đại diện bởi các interface mà đã viết ở phần trên.

Mỗi nhà máy sản xuất tương ứng với một biến thể sản phẩm cụ thể

Bây giờ, làm thế nào tiếp? Đối với mỗi biến thể của sản phẩm, mình đã tạo một class cho từng nhà máy dựa trên một interface Abstract Factory. Nhà máy là một class trả lại các sản phẩm của loại cụ thể. Ví dụ: ModernFurnitureFactory chỉ có thể tạo các đối tượng ModernChair, ModernSofa, ModernCoffeeTable.

Khách hàng phải hoạt động với cả nhà máy và sản phẩm thông qua abstract interface tương ứng. 

Kiến trúc

Structure Abstract Factory

  1. Abstract Product khai báo interface cho một tập hợp các sản phẩm riêng biệt nhưng có liên quan tạo nên một họ sản phẩm.
  2. Concrete Products là các thuộc tính thêm vào các sản phẩm trừu tượng, được nhóm theo các biến thể. Mỗi sản phẩm trừu tượng (Ghế / Sofa) phải được thực hiện trong các biến thể nhất định (Hiện đại, Cổ điển,.. ).
  3. Abstract Factory là interface khai báo một tập hợp các phương thức để tạo từng sản phẩm trừu tượng.
  4. Concrete Factories thực hiện các method của abstract factory. Mỗi nhà máy cụ thể tương ứng với một biến thể cụ thể của sản phẩm và chỉ được tạo ra biến thể của sản phẩm đó.
  5. Mặc dù các nhà máy cụ thể tạo ra các sản phẩm cụ thể, nhưng chữ ký của các method của họ phải trả về các sản phẩm trừu tượng tương ứng. Client có thể làm việc với bất ký biến thể của nhà máy/ sản phẩm cụ thể nào, miễn là nó giao tiếp với các đối tượng thông qua các abstract interface.

Khi nào thì áp dụng?

Sử dụng Design Pattern Abstract Factory khi code của bạn cần hoạt động với nhiều nhóm sản phẩm liên quan khác nhau, nhưng bạn không muốn nó phụ thuộc vào các lớp cụ thể của các sản phẩm đó – chúng có thể chưa biết trước hoặc bạn chỉ muốn cho phép khả năng mở rộng trong tương lai

Abstract factory cung cấp cho bạn một interface để tạo ra các đối tượng từ mỗi class của họ sản phẩm. Miễn là code của bạn tạo ra thông qua các interface này, bạn không phải lo lắng về việc tạo sai biến thể của sản phẩm không khớp với các sản phẩm đã được tạo trong ứng dụng của bạn. 

  • Cân nhắc triển khai Abstract Factory khi bạn có một class với một tập hợp các phương thức Factory làm các trách nhiệm chính của nó
  • Trong một chương trình được thiết kế tốt, mỗi class chỉ chịu trách nhiệm về một nhiệm vụ. Khi một class xử lý nhiều loại sản phẩm, nó có thể cần được tách ra các phương thức Factory thành Abstract Factory.

Cách triển khai

  1. Lập sơ đồ ma trận gồm các loại sản phẩm riêng biệt so với các biến thể của các sản phẩm này.
  2. Khai báo các abstract interface sản phẩm cho các loại sản phẩm. Sau đó, implement interface này vào tất cả class của sản phẩm.
  3. Khai báo abstract factory interface với một tập hợp các phương pháp tạo cho tất cả sản phẩm trừu tượng.
  4. Triển khai một tập hợp các factory cụ thể, mỗi class cho một biến thể sản phẩm.
  5. Tạo code khởi tạo trong ứng dụng. Nó sẽ khởi tạo một trong các class của các factory cụ thể, tuỳ thuộc vào cấu hình ứng dụng hoặc môi trường hiện tại. Truyền đối tượng factory này cho tất các cả class tạo sản phẩm.
  6.  Thay thế tất cả các câu lệnh gọi trực tiếp thành các phương thức khởi tạo thích hợp trên đối tượng factory.

Ưu và nhược điểm

  • Bạn có thể chắc chắn rằng các sản phẩm bạn nhận được từ factory tương thích với nhau.
  • Bạn tránh ghép nối chặt chẽ giữa sản phẩm cụ thể với khách hàng.
  • Nguyên tắc Single Responsibility. Bạn có thể tạo ra sản phẩm vào một nơi, có thể chỉnh sửa dễ dàng hơn.
  • Nguyên tắc Open/Close. Bạn có thể giới thiệu các biến thể mới của sản phẩm mà không cần vi phạm đoạn code hiện có
  • Code có thể trở nên phức tạp hơn mức bình thường, vì rất nhiều interface và class mới có thể tạo ra pattern.

Code ví dụ

Các bạn có thể tham khảo code ví dụ ở đây.

Chúc các bạn có ngày học tập hiệu quả. Và đừng quên tham gia Group để trao đổi kiến thức nhiều hơn nhé.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x