close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

C# Design patterns: Abstract Factory

Abstract Factory là một mẫu thiết kế khởi tạo, giải quyết vấn đề tạo ra toàn bộ họ sản phẩm mà không chỉ định các lớp cụ thể của chúng.

Abstract Factory định nghĩa một giao diện để tạo tất cả các sản phẩm riêng biệt nhưng để việc tạo sản phẩm thực tế cho các lớp factory cụ thể. Mỗi loại factory tương ứng với một loại sản phẩm nhất định.

Mã client gọi các phương thức khởi tạo của một đối tượng factory thay vì tạo sản phẩm trực tiếp bằng lệnh gọi phương thức khởi tạo (toán tử new). Vì một factory tương ứng với một biến thể sản phẩm duy nhất nên tất cả các sản phẩm của factory đó sẽ tương thích.

Client chỉ hoạt động với các factory và sản phẩm thông qua các giao diện trừu tượng của chúng. Điều này cho phép client hoạt động với mọi biến thể sản phẩm, được tạo bởi đối tượng factory. Bạn chỉ cần tạo một lớp factory cụ thể mới và chuyển nó cho client.

Cách sử dụng mẫu trong C#

Sử dụng: Mẫu Abstract Factory khá phổ biến trong C#. Nhiều framework và thư viện sử dụng nó để cung cấp cách mở rộng và tùy chỉnh các thành phần tiêu chuẩn của chúng.

Nhận biết: Mẫu dễ dàng được nhận ra bằng các phương thức trả về một đối tượng factory. Sau đó, factory được sử dụng để tạo ra các thành phần phụ cụ thể.

Chương trình minh họa

Ví dụ này minh họa cấu trúc của mẫu thiết kế Abstract Factory. Nó tập trung vào việc trả lời những câu hỏi sau:

  • Nó bao gồm những lớp nào?
  • Các lớp này có vai trò gì?
  • Các thành phần của mẫu có liên quan với nhau theo cách nào?

Program.cs

using System;
namespace DesignPatterns.AbstractFactory.Conceptual
{
    // Giao diện Abstract Factory khai báo một tập hợp các phương thức trả về các sản phẩm trừu 
    // tượng khác nhau. Những sản phẩm này được gọi là một họ và có liên quan với nhau theo 
    // một chủ đề hoặc khái niệm. Các sản phẩm của một họ thường có thể cộng tác với nhau. 
    // Một họ sản phẩm có thể có một số biến thể, nhưng các sản phẩm của biến thể này 
    // không tương thích với các sản phẩm của biến thể khác.
    public interface IAbstractFactory
    {
        IAbstractProductA CreateProductA();
        IAbstractProductB CreateProductB();
    }
    // Các Concrete Factory sản xuất một họ sản phẩm thuộc một biến thể duy nhất. Nhà máy đảm 
    // bảo rằng các sản phẩm tạo ra là tương thích. Lưu ý rằng chữ ký của các phương thức của 
    // Concrete Factory trả về một sản phẩm trừu tượng (abstract product), trong khi bên trong 
    // phương thức, một sản phẩm cụ thể được khởi tạo.
    class ConcreteFactory1 : IAbstractFactory
    {
        public IAbstractProductA CreateProductA()
        {
            return new ConcreteProductA1();
        }
        public IAbstractProductB CreateProductB()
        {
            return new ConcreteProductB1();
        }
    }
    // Mỗi Concrete Factory có một biến thể sản phẩm tương ứng.
    class ConcreteFactory2 : IAbstractFactory
    {
        public IAbstractProductA CreateProductA()
        {
            return new ConcreteProductA2();
        }
        public IAbstractProductB CreateProductB()
        {
            return new ConcreteProductB2();
        }
    }
    // Mỗi sản phẩm riêng biệt của một họ sản phẩm nên có một giao diên cơ sở.
    // Tất cả các biến thể của sản phẩm đều phải hiện thực giao diện này.
    public interface IAbstractProductA
    {
        string UsefulFunctionA();
    }
    // Concrete Product được tạo ra tương ứng với Concrete Factory.
    class ConcreteProductA1 : IAbstractProductA
    {
        public string UsefulFunctionA()
        {
            return "The result of the product A1.";
        }
    }
    class ConcreteProductA2 : IAbstractProductA
    {
        public string UsefulFunctionA()
        {
            return "The result of the product A2.";
        }
    }
    // Đây là giao diện cơ sở của một sản phẩm khác. Tất cả các sản phẩm có thể tương 
    // tác với nhau, nhưng chỉ có thể thích hợp tương tác giữa các sản phẩm của cùng 
    // một biến thể cụ thể.
    public interface IAbstractProductB
    {
        // Sản phẩm B có thể làm mọi thứ của nó...
        string UsefulFunctionB();
        // ...nhưng cũng có thể tương tác với sản phẩm A.
        //
        // Abstract Factory đảm bảo rằng tất cả các sản phẩm mà nó tạo ra đều 
        // có cùng một biến thể và do đó, tương thích.
        string AnotherUsefulFunctionB(IAbstractProductA collaborator);
    }
    // Concrete Product được tạo ra tương ứng bởi Concrete Factory.
    class ConcreteProductB1 : IAbstractProductB
    {
        public string UsefulFunctionB()
        {
            return "The result of the product B1.";
        }
        // Biến thể, Sản phẩm B1, chỉ có thể hoạt động chính xác với biến thể, Sản phẩm A1. 
        // Tuy nhiên, nó chấp nhận bất kỳ thể hiện nào của AbstractProductA làm đối số.
        public string AnotherUsefulFunctionB(IAbstractProductA collaborator)
        {
            var result = collaborator.UsefulFunctionA();
            return $"The result of the B1 collaborating with the ({result})";
        }
    }
    class ConcreteProductB2 : IAbstractProductB
    {
        public string UsefulFunctionB()
        {
            return "The result of the product B2.";
        }
       // Biến thể, Sản phẩm B2, chỉ có thể hoạt động chính xác với biến thể, Sản phẩm A2. 
       // Tuy nhiên, nó chấp nhận bất kỳ thể hiện nào của AbstractProductA làm đối số.
        public string AnotherUsefulFunctionB(IAbstractProductA collaborator)
        {
            var result = collaborator.UsefulFunctionA();
            return $"The result of the B2 collaborating with the ({result})";
        }
    }
    // Mã Client chỉ hoạt động với các nhà máy và sản phẩm thông qua các kiểu trừu tượng: 
    // AbstractFactory và AbstractProduct. Điều này cho phép bạn truyền bất kỳ lớp con nào 
    // của nhà máy hoặc sản phẩm sang mã client mà không làm hỏng nó.
    class Client
    {
        public void Main()
        {
            // Mã Client  có thể hoạt động với bất kỳ lớp Concrete Factory nào.
            Console.WriteLine("Client: Testing client code with the first factory type...");
            ClientMethod(new ConcreteFactory1());
            Console.WriteLine();
            Console.WriteLine("Client: Testing the same client code with the second factory type...");
            ClientMethod(new ConcreteFactory2());
        }
        public void ClientMethod(IAbstractFactory factory)
        {
            var productA = factory.CreateProductA();
            var productB = factory.CreateProductB();
            Console.WriteLine(productB.UsefulFunctionB());
            Console.WriteLine(productB.AnotherUsefulFunctionB(productA));
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            new Client().Main();
        }
    }
}

Kết quả:

Client: Testing client code with the first factory type:
The result of the product B1.
The result of the B1 collaborating with the (The result of the product A1.)
Client: Testing the same client code with the second factory type:
The result of the product B2.
The result of the B2 collaborating with the (The result of the product A2.)

Đã đăng vào

trong

,

bởi

Thẻ:

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *