Tổng quan về Abstract Factory Design Pattern


Được xây dựng dựa trên Factory Pattern và được coi là một factory cao cấp nhất, là phương pháp tạo ra một Super-factory dùng để tạo ra các Factory khác. Hay còn được gọi là Factory của các Factory.  


I. Giới thiệu

Abstract Factory (Kit) là một design pattern thuộc nhóm Creational Pattern Design – những mẫu thiết kế cho việc khởi tạo đối tượng của lớp. Được xây dựng dựa trên Factory Pattern và được coi là một factory cao cấp nhất, là phương pháp tạo ra một Super-factory dùng để tạo ra các Factory khác. Hay còn được gọi là Factory của các Factory. 

Trong Abstract Factory pattern, một interface có nhiệm vụ tạo ra một Factory của các object có liên quan tới nhau mà không cần phải chỉ ra trực tiếp các class của object. Mỗi Factory được tạo ra có thể tạo ra các object bằng phương pháp giống như Factory pattern.

Hãy tưởng tượng, Abstract factory như là một Factory lớn chứa nhiều nhà Factory nhỏ, trong các Factory nhỏ đó có những xưởng sản xuất, các xưởng đó tạo ra những sản phẩm khác nhau.

II. Kiến trúc

Các thành phần trong mô hình:

  • AbstractFactory: Khai báo dạng interface hoặc abstract class chứa các phương thức để tạo ra các đối tượng Abstract Product.
  • ConcreteFactory (Factory1, Factory2,...): Xây dựng, cài đặt, thực hiện các phương thức được tạo nên từ Abstract Factory. Mỗi ConcreteFactory tương ứng với một biến thể khác của product và chỉ tạo ra những biến thể của sản phẩm đó.
  • AbstractProduct (IProductA, IProductB): Khai báo dạng interface hoặc abstract class cho một tập hợp các product riêng biệt nhưng có liên quan đến nhau. 
  • ConcreteProduct (ProductA1, ProductA2, ProductB1,...): Là các cách triển khai khác nhau của AbstractProduct gồm nhiều các biến thể. Mỗi nhóm AbstractProduct phải được thực hiện cùng các biến thể nhất định. 
  • Client: là đối tượng sử dụng AbstractFactory, AbstractProduct và client cũng có thể làm việc với bất kỳ biến thể nào của ConcreteFactory, ConcreteProduct, miễn là nó có giao tiếp với đối tượng (object) thông qua abstract interface

Ví dụ: Một quán ăn chuyên bán Hủ tiếu gồm Hủ tiếu giòHủ tiếu nạc. Sau một thời gian quán quyết định bán thêm Mỳ. Với lợi thế là đã có kinh nghiệm từ bán Hủ tiếu nên công ty vẫn giữ nguyên liệu giònạc.

Quán quyết định tách ra làm 2 người phụ trách: 1 cho món giò, 1 cho món nạc, cả 2 người đều có thể làm ra món Hủ tiếuMỳ

Khi khách hàng cần mua món ăn nào, khách hàng (Client) chỉ cần đến quán ăn để mua (MonanFactory). Khi đó ứng với từng món ăn và topping sẽ được chuyển về cho người phụ trách (LoaiGioFactory hoặc LoaiNacFactory) tương ứng.

Hệ thống được minh họa như sau:

III. Source code minh họa với C#

  • Tạo các Abstract Product
    interface HuTieu
    {
        string GetModelDetails();
    }

    interface My
    {
        string GetModelDetails();
    }

 

  • Tạo các Product
    class HuTieuNac : HuTieu
    {
        public string GetModelDetails()
        {
            return "HU TIEU NAC cua em day";
        }
    }
    
     class HuTieuGio : HuTieu
    {
        public string GetModelDetails()
        {
            return "HU TIEU GIO cua em day";
        }
    }

    class MyNac : My
    {
        public string GetModelDetails()
        {
            return "MY NAC cua em day";
        }
    }
    
    class MyGio : My
    {
        public string GetModelDetails()
        {
            return "MY GIO cua em day";
        }
    }

 

  • Tạo  Abstract Factory
    interface MonAnFactory
    {
        HuTieu LayToHuTieu();
        My LayToMy();
    }

 

  • Tạo các Factory con
    class LoaiGioFactory : MonAnFactory
    {
        public HuTieu LayToHuTieu()
        {
            return new HuTieuGio();
        }

        public My LayToMy()
        {
            return new MyGio();
        }
    }

    class LoaiNacFactory : MonAnFactory
    {
        public HuTieu LayToHuTieu()
        {
            return new HuTieuNac();
        }

        public My LayToMy()
        {
            return new MyNac();
        }
    }

 

  • Tạo Client
    class Client
    {
        HuTieu hutieu;
        My my;
    
        public Client(MonAnFactory factory)
        {
            hutieu = factory.LayToHuTieu();
            my = factory.LayToMy();
        }

        public string GetHuTieuDetails()
        {
            return hutieu.GetModelDetails();
        }

        public string GetMyDetails()
        {
            return my.GetModelDetails();
        }
    }

 

  • Sử dụng
    class Program
    {
        static void Main(string[] args)
        {
            MonNuocFactory loaiNac = new LoaiNacFactory();
            Client NacClient = new Client(loaiNac);
            MonNuocFactory loaiGio = new LoaiGioFactory();
            Client GioClient = new Client(loaiGio);

            Console.WriteLine("********* HU TIEU **********");
            Console.WriteLine(NacClient.GetHuTieuDetails());
            Console.WriteLine(GioClient.GetHuTieuDetails());

            Console.WriteLine("******* MY **********");
            Console.WriteLine(NacClient.GetMyDetails());
            Console.WriteLine(GioClient.GetMyDetails());

            Console.ReadKey();
        }
    }

IV. Ưu & nhược điểm

    1. Ưu điểm

  • Có thể đảm bảo các đối tượng product nhận được từ factory sẽ tương thích với nhau.
  • Tránh được những ràng buộc chặt chẽ giữa concrete products và client code.
  • Nguyên tắc đơn lẻ: có thể trích xuất code tạo product vào một nơi và hỗ trợ code dễ dàng.
  • Nguyên tắc mở/ đóng: có thể khởi tạo những bản mới của product mà không cần phá vỡ client code hiện có.

    2. Nhược điểm

  • Code có thể trở nên phức tạp hơn mức bình thường, vì có rất nhiều interfaces và classes được khởi tạo cùng với mẫu.

V. Khi nào thì sử dụng

Sử dụng Abstract Facotry khi cần làm việc với các product có tính chất gần giống nhau và liên quan đến nhau và không cần phụ thuộc vào các định nghĩa có sẵn trong class đó:

  • Phía client sẽ không phụ thuộc vào việc những sản phẩm được tạo ra như thế nào.
  • Ứng dụng sẽ được cấu hình với một hoặc nhiều họ sản phẩm.
  • Các đối tượng cần phải được tạo ra như một tập hợp để có thể tương thích với nhau.

VI. Design Pattern liên quan

  • Factory Method: Abstract Factory class thường dựa trên một số phương thức Factory, nhưng cũng có thể sử dụng Prototype để kết hợp các phương thức trong Abstract class đó
  • Builder: Builder tập trung vào việc xây dựng các đối tượng phức tạp theo từng bước. Abstract Factory chuyên tạo các family đối tượng liên quan. Abstract Factory trả lại product ngay lập tức, trong khi Builder cho phép bạn chạy một số bước xây dựng bổ sung trước khi tìm nạp product.
  • Prototype: Abstract Factory thường dựa trên một tập hợp Factory Method, nhưng cũng có thể sử dụng Prototype để soạn các phương thức trên các lớp này.
  • Singleton: Abstract Factory, Factory và Prototype đều được triển khai dưới dạng Singleton.

 

Tài liệu tham khảo

[1] Refactoring.Guru

[2] Design Patterns for Dummies, Steve Holzner, PhD

[3] Head First, Eric Freeman

[4] Gang of Four Design Patterns 4.0

[5] Dive into Design Pattern

Chia sẽ bài viết :