
C# 抽象工厂模式讲解和代码示例
抽象工厂是一种创建型设计模式, 它能创建一系列相关的对象, 而无需指定其具体类。
抽象工厂定义了用于创建不同产品的接口, 但将实际的创建工作留给了具体工厂类。 每个工厂类型都对应一个特定的产品变体。
在创建产品时, 客户端代码调用的是工厂对象的构建方法, 而不是直接调用构造函数 ( new
操作符)。 由于一个工厂对应一种产品变体, 因此它创建的所有产品都可相互兼容。
客户端代码仅通过其抽象接口与工厂和产品进行交互。 该接口允许同一客户端代码与不同产品进行交互。 你只需创建一个具体工厂类并将其传递给客户端代码即可。
如果你不清楚工厂、 工厂方法和抽象工厂模式之间的区别, 请参阅工厂模式比较。
复杂度:
流行度:
使用示例: 抽象工厂模式在 C# 代码中很常见。 许多框架和程序库会将它作为扩展和自定义其标准组件的一种方式。
识别方法: 我们可以通过方法来识别该模式——其会返回一个工厂对象。 接下来, 工厂将被用于创建特定的子组件。
概念示例
本例说明了抽象工厂设计模式的结构并重点回答了下面的问题:
- 它由哪些类组成?
- 这些类扮演了哪些角色?
- 模式中的各个元素会以何种方式相互关联?
Program.cs: 概念示例
using System; namespace RefactoringGuru.DesignPatterns.AbstractFactory.Conceptual { // The Abstract Factory interface declares a set of methods that return // different abstract products. These products are called a family and are // related by a high-level theme or concept. Products of one family are // usually able to collaborate among themselves. A family of products may // have several variants, but the products of one variant are incompatible // with products of another. public interface IAbstractFactory { IAbstractProductA CreateProductA(); IAbstractProductB CreateProductB(); } // Concrete Factories produce a family of products that belong to a single // variant. The factory guarantees that resulting products are compatible. // Note that signatures of the Concrete Factory's methods return an abstract // product, while inside the method a concrete product is instantiated. class ConcreteFactory1 : IAbstractFactory { public IAbstractProductA CreateProductA() { return new ConcreteProductA1(); } public IAbstractProductB CreateProductB() { return new ConcreteProductB1(); } } // Each Concrete Factory has a corresponding product variant. class ConcreteFactory2 : IAbstractFactory { public IAbstractProductA CreateProductA() { return new ConcreteProductA2(); } public IAbstractProductB CreateProductB() { return new ConcreteProductB2(); } } // Each distinct product of a product family should have a base interface. // All variants of the product must implement this interface. public interface IAbstractProductA { string UsefulFunctionA(); } // Concrete Products are created by corresponding Concrete Factories. 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."; } } // Here's the the base interface of another product. All products can // interact with each other, but proper interaction is possible only between // products of the same concrete variant. public interface IAbstractProductB { // Product B is able to do its own thing... string UsefulFunctionB(); // ...but it also can collaborate with the ProductA. // // The Abstract Factory makes sure that all products it creates are of // the same variant and thus, compatible. string AnotherUsefulFunctionB(IAbstractProductA collaborator); } // Concrete Products are created by corresponding Concrete Factories. class ConcreteProductB1 : IAbstractProductB { public string UsefulFunctionB() { return "The result of the product B1."; } // The variant, Product B1, is only able to work correctly with the // variant, Product A1. Nevertheless, it accepts any instance of // AbstractProductA as an argument. 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."; } // The variant, Product B2, is only able to work correctly with the // variant, Product A2. Nevertheless, it accepts any instance of // AbstractProductA as an argument. public string AnotherUsefulFunctionB(IAbstractProductA collaborator) { var result = collaborator.UsefulFunctionA(); return $"The result of the B2 collaborating with the ({result})"; } } // The client code works with factories and products only through abstract // types: AbstractFactory and AbstractProduct. This lets you pass any // factory or product subclass to the client code without breaking it. class Client { public void Main() { // The client code can work with any concrete factory class. 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(); } } }
Output.txt: 执行结果
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.)