Abstract factory là một trong các design pattern được áp dụng khá phổ biến trong khi thiết kế và lập trình. Nó cung cấp một cách thức chung để tạo ra một họ các đối tượng có quan hệ hoặc phụ thuộc nhau mà không cần chỉ rõ các lớp cụ thể trong họ đó.
UML
Abstract factory được mô hình hóa bởi UML như sau:
Các thành phần tham gia
- 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
- ConcreteFactory: Xây dựng, cài đặt các phương thức tạo các đối tượng cụ thể
- AbstractProduct: Khai báo dạng interface hoặc abstract class để định nghĩa đối tượng abstract
- Product: Cài đặt của các đối tượng cụ thể, cài đặt các phương thức được quy định tại AbstractProduct
- Client: là đối tượng sử dụng AbstractFactory và các AbstractProduct
Cài đặt AbstractFactory trong C#
Ta thực hiện cài đặt lần lượt các lớp trong mô hình UML trên bằng C#. Để đơn giản, AbstractProductA không chứa hàm nghiệp vụ nào, AbstractProductB chứa 1 hàm nghiệp vụ là Interact nhận tham số đầu vào là AbstractProductA và in ra màn hình thông báo tên lớp thực sự của AbstractProductB và AbstractProductA:
class MainApp { public static void Main() { // Abstract factory #1 AbstractFactory factory1 = new ConcreteFactory1(); Client client1 = new Client(factory1); client1.Run(); // Abstract factory #2 AbstractFactory factory2 = new ConcreteFactory2(); Client client2 = new Client(factory2); client2.Run(); Console.ReadKey(); } } //The 'AbstractFactory' abstract class abstract class AbstractFactory { public abstract AbstractProductA CreateProductA(); public abstract AbstractProductB CreateProductB(); } // The 'ConcreteFactory1' class class ConcreteFactory1 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA1(); } public override AbstractProductB CreateProductB() { return new ProductB1(); } } // The 'ConcreteFactory2' class class ConcreteFactory2 : AbstractFactory { public override AbstractProductA CreateProductA() { return new ProductA2(); } public override AbstractProductB CreateProductB() { return new ProductB2(); } } // The 'AbstractProductA' abstract class. // Không chứa nghiệp vụ gì abstract class AbstractProductA { } // The 'AbstractProductB' abstract class abstract class AbstractProductB { // In ra màn hình thông báo tên lớp thực sự của AbstractProductB và AbstractProductA public abstract void Interact(AbstractProductA a); } // The 'ProductA1' class class ProductA1 : AbstractProductA { } // The 'ProductB1' class class ProductB1 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } // The 'ProductA2' class class ProductA2 : AbstractProductA { } // The 'ProductB2' class class ProductB2 : AbstractProductB { public override void Interact(AbstractProductA a) { Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name); } } // The 'Client' class. class Client { private AbstractProductA _abstractProductA; private AbstractProductB _abstractProductB; // Constructor public Client(AbstractFactory factory) { _abstractProductB = factory.CreateProductB(); _abstractProductA = factory.CreateProductA(); } public void Run() { _abstractProductB.Interact(_abstractProductA); } }
Kết quả:
ProductB1 interacts with ProductA1
|
Nhận xét: Abstract Factory dựa trên tính thừa kế và đa hình đề cài đặt và sử dụng.
Một ví dụ trong thực tế
Có một bài toán thực tế và cần mô phỏng lại như sau: Trong thế giới động vật (AnimalWorld) có các loài động vật ăn cỏ (Herbivore) và các loài động vật ăn thịt (Carnivore). Ở mỗi châu lục (Continent) lại có các loài đặc thù khác nhau thuộc 2 nhóm trên. Ví dụ ở châu Phi (Africa) có Sư tử (Lion) và Dê núi (Wildebeest), châu Mỹ (America) có Sói (Wolf) và Bò rừng Bi-dông (Bison). Biết rằng bọn ăn thịt chỉ ăn những loài nó biết.
Ta sẽ áp dụng Abstract Factory để mô phỏng lại bài toán trên. Tôi sử dụng C# và cách thức cài đặt như bên trên trong đó lớp Herbivore cũng không có nghiệp vụ gì và lớp Carnivore có phương thức Eat (thực hiện in ra con gì ăn con gì).
class MainApp { public static void Main() { // Tạo ra các loài động vật ở châu Phi ContinentFactory africa = new AfricaFactory(); AnimalWorld world = new AnimalWorld(africa); world.RunFoodChain(); // Tạo ra các loài động vật ở châu Mỹ ContinentFactory america = new AmericaFactory(); world = new AnimalWorld(america); world.RunFoodChain(); Console.ReadKey(); } } // The 'AbstractFactory' abstract class abstract class ContinentFactory { // tạo ra động vật ăn cỏ public abstract Herbivore CreateHerbivore(); // tạo ra động vật ăn thịt public abstract Carnivore CreateCarnivore(); } // The 'ConcreteFactory1' class class AfricaFactory : ContinentFactory { public override Herbivore CreateHerbivore() { return new Wildebeest(); } public override Carnivore CreateCarnivore() { return new Lion(); } } // The 'ConcreteFactory2' class class AmericaFactory : ContinentFactory { public override Herbivore CreateHerbivore() { return new Bison(); } public override Carnivore CreateCarnivore() { return new Wolf(); } } // The 'AbstractProductA' abstract class abstract class Herbivore { } // The 'AbstractProductB' abstract class abstract class Carnivore { public abstract void Eat(Herbivore h); } // The 'ProductA1' class class Wildebeest : Herbivore { } // The 'ProductB1' class class Lion : Carnivore { public override void Eat(Herbivore h) { // Eat Wildebeest Console.WriteLine(this.GetType().Name + " eats " + h.GetType().Name); } } // The 'ProductA2' class class Bison : Herbivore { } // The 'ProductB2' class class Wolf : Carnivore { public override void Eat(Herbivore h) { // Eat Bison Console.WriteLine(this.GetType().Name + " eats " + h.GetType().Name); } } // The 'Client' class class AnimalWorld { private Herbivore _herbivore; private Carnivore _carnivore; // Constructor public AnimalWorld(ContinentFactory factory) { _carnivore = factory.CreateCarnivore(); _herbivore = factory.CreateHerbivore(); } public void RunFoodChain() { _carnivore.Eat(_herbivore); } }
Kết quả:
Lion eats Wildebeest |