Abstract Factory Pattern in C#
Bài đăng này đã không được cập nhật trong 3 năm
Giới thiệu
Hẳn đã là 1 developer có tâm thì bạn luôn muốn code của mình viết ra không chỉ dễ đọc, dễ hiểu mà còn có thể dễ bảo trì. Design parterns chắc chắn là cảnh giới mà mỗi developer chất luôn muốn đạt được để có thể nâng tầm code mà mình viết ra. Đó còn là giải pháp cho các vấn đề về thiết kế mà bạn sẽ thấy rất nhiều trong việc phát triển phần mềm trong thực tế. Patterns ở đây chính là việc các object có thể được sử dụng lại một cách khôn ngoan thông qua cấu trúc và cách nó tương tác với các object khác. Quyển "The 23 Gang of Four (GoF) Patterns" chứa đựng những pattern thường được dùng làm nền tảng cho những pattern khác, chia ra làm 3 nhóm: Creational, Structural và Behavioral.
Trong bài viết hôm nay mình sẽ giới thiệu cho các bạn về Abstract Factory Pattern, một pattern thường được sử dụng để tạo ra những object có những điểm chung và có những tính chất riêng.
Định nghĩa
Abstract Factory pattern giống như 1 siêu nhà máy sản suất, để tạo ra những nhà máy khác (để tạo ra object). Siêu máy này còn được gọi là máy của các máy (factory of factories). Kiểu design pattern này là 1 kiểu của creational pattern, và là 1 trong những cách hay và hiệu quả nhất để tạo ra các object. Trong Abstract Factory pattern, 1 interface chịu trách nhiệm để tạo ra 1 nhà máy cho những object tương tự nhau mà không chỉ định rõ ra class của chúng. Mỗi nhà máy tạo ra có thể đưa ra những object theo kiểu nhà máy khác nhau (Factory Pattern). Độ sử dụng thường xuyên: Rất cao
UML Diagram
Các thành phần
- AbstractFactory (ContinentFactory - nhà máy Lục địa) khai báo 1 interace cho các hàm để tạo ra các abstract product
- ConcreteFactory (AfricaFactory, AmericaFactory - nhà máy châu Phi, nhà máy châu Mỹ) triển khai hàm từ interface để tạo ra các object product cụ thể
- AbstractProduct (Herbivore, Carnivore - động vật ăn cỏ, động vật ăn thịt) khai báo 1 interface cho loại product
- Product (Wildebeest, Lion, Bison, Wolf - dê rừng, sư tử, bò rừng, chó sói)
- đưa ra những object product được tạo bởi các ConcreteFactory
- triển khai Abstract Product interface
- Client (AnimalWorld) sử dụng các interface đã khai báo bới các class AbstarctFactory và AbstractProduct
Cấu trúc code trong C#
using System;
namespace DoFactory.GangOfFour.Abstract.Structural
{
/// <summary>
/// MainApp startup class for Structural
/// Abstract Factory Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
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();
// Wait for user input
Console.ReadKey();
}
}
/// <summary>
/// The 'AbstractFactory' abstract class
/// </summary>
abstract class AbstractFactory
{
public abstract AbstractProductA CreateProductA();
public abstract AbstractProductB CreateProductB();
}
/// <summary>
/// The 'ConcreteFactory1' class
/// </summary>
class ConcreteFactory1 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA1();
}
public override AbstractProductB CreateProductB()
{
return new ProductB1();
}
}
/// <summary>
/// The 'ConcreteFactory2' class
/// </summary>
class ConcreteFactory2 : AbstractFactory
{
public override AbstractProductA CreateProductA()
{
return new ProductA2();
}
public override AbstractProductB CreateProductB()
{
return new ProductB2();
}
}
/// <summary>
/// The 'AbstractProductA' abstract class
/// </summary>
abstract class AbstractProductA
{
}
/// <summary>
/// The 'AbstractProductB' abstract class
/// </summary>
abstract class AbstractProductB
{
public abstract void Interact(AbstractProductA a);
}
/// <summary>
/// The 'ProductA1' class
/// </summary>
class ProductA1 : AbstractProductA
{
}
/// <summary>
/// The 'ProductB1' class
/// </summary>
class ProductB1 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}
/// <summary>
/// The 'ProductA2' class
/// </summary>
class ProductA2 : AbstractProductA
{
}
/// <summary>
/// The 'ProductB2' class
/// </summary>
class ProductB2 : AbstractProductB
{
public override void Interact(AbstractProductA a)
{
Console.WriteLine(this.GetType().Name +
" interacts with " + a.GetType().Name);
}
}
/// <summary>
/// The 'Client' class. Interaction environment for the products.
/// </summary>
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
ProductB2 interacts with ProductA2
Cấu trúc trong dự án thực tế
using System;
namespace DoFactory.GangOfFour.Abstract.RealWorld
{
/// <summary>
/// MainApp startup class for Real-World
/// Abstract Factory Design Pattern.
/// </summary>
class MainApp
{
/// <summary>
/// Entry point into console application.
/// </summary>
public static void Main()
{
// Create and run the African animal world
ContinentFactory africa = new AfricaFactory();
AnimalWorld world = new AnimalWorld(africa);
world.RunFoodChain();
// Create and run the American animal world
ContinentFactory america = new AmericaFactory();
world = new AnimalWorld(america);
world.RunFoodChain();
// Wait for user input
Console.ReadKey();
}
}
/// <summary>
/// The 'AbstractFactory' abstract class
/// </summary>
abstract class ContinentFactory
{
public abstract Herbivore CreateHerbivore();
public abstract Carnivore CreateCarnivore();
}
/// <summary>
/// The 'ConcreteFactory1' class
/// </summary>
class AfricaFactory : ContinentFactory
{
public override Herbivore CreateHerbivore()
{
return new Wildebeest();
}
public override Carnivore CreateCarnivore()
{
return new Lion();
}
}
/// <summary>
/// The 'ConcreteFactory2' class
/// </summary>
class AmericaFactory : ContinentFactory
{
public override Herbivore CreateHerbivore()
{
return new Bison();
}
public override Carnivore CreateCarnivore()
{
return new Wolf();
}
}
/// <summary>
/// The 'AbstractProductA' abstract class
/// </summary>
abstract class Herbivore
{
}
/// <summary>
/// The 'AbstractProductB' abstract class
/// </summary>
abstract class Carnivore
{
public abstract void Eat(Herbivore h);
}
/// <summary>
/// The 'ProductA1' class
/// </summary>
class Wildebeest : Herbivore
{
}
/// <summary>
/// The 'ProductB1' class
/// </summary>
class Lion : Carnivore
{
public override void Eat(Herbivore h)
{
// Eat Wildebeest
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}
/// <summary>
/// The 'ProductA2' class
/// </summary>
class Bison : Herbivore
{
}
/// <summary>
/// The 'ProductB2' class
/// </summary>
class Wolf : Carnivore
{
public override void Eat(Herbivore h)
{
// Eat Bison
Console.WriteLine(this.GetType().Name +
" eats " + h.GetType().Name);
}
}
/// <summary>
/// The 'Client' class
/// </summary>
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
Wolf eats Bison
Kết luận
Với Abstract Pattern thì việc tạo ra các object với những đặc tính có liên quan và đặc tính riêng phát huy được tính trừu tượng trong hướng đối tượng, đồng thời code nhìn sạch sẽ và khoa học. Hy vọng bài viết có ích cho các bạn.
Bài viết tham khảo nguồn từ: http://www.dofactory.com/net/abstract-factory-design-pattern
All rights reserved