抽象工厂(Abstract Factory)学习笔记

抽象工厂(Abstract Factory)学习笔记,同时包含在Unity中的应用

AssistedByChatGPT

抽象工厂(Abstract Factory)模式主要目的是提供一个接口,用于创建一系列相关或依赖对象的家族,而无需指定它们具体的类。通过这种方式,一个系统可以独立于它如何创建、组合和表示它的产品,这样系统就只需要知道如何从抽象工厂中获取产品的接口,而无需了解具体的实现细节。

核心组件

抽象工厂模式涉及以下几个核心组件:

  1. 抽象工厂(Abstract Factory):这是一个接口,声明了一系列创建抽象产品的方法。
  2. 具体工厂(Concrete Factory):实现抽象工厂接口的具体类。每个具体工厂都能够按照工厂方法模式产生一组具体产品。
  3. 抽象产品(Abstract Product):为一类产品对象声明一个接口。所有类型的产品对象都要支持这个接口。
  4. 具体产品(Concrete Product):抽象产品的具体子类。具体工厂负责创建具体产品的实例。
  5. 客户端(Client):仅使用由抽象工厂和抽象产品的接口定义的方法。

应用场景

抽象工厂模式特别适用于以下情况:

  • 当需要创建的对象是一系列相互关联或相互依赖的产品族时。
  • 当系统不应依赖于产品类实例如何被创建、组合和表示的时候。
  • 当系统需要被配置为一个有多个可能变体的产品族中的一个时。

优势

  • 隔离具体类的生成:抽象工厂模式帮助将产品类的生成代码与使用产品的代码分离,增加了客户代码的灵活性。
  • 易于交换产品系列:因为具体工厂类在一个应用中只需要在初始化阶段被配置一次,之后整个应用生命周期中就可以使用这个产品系列,这使得改变一个应用的产品系列变得容易。
  • 增强了程序的一致性:当一个产品族中的多个对象被设计成一起工作时,它能够保证客户端始终只使用同一个产品族中的对象。

示例

假设我们有一个应用,需要适配多种样式的用户界面元素,比如按钮和文本框,这些元素根据操作系统的不同(比如Windows和MacOS)有不同的显示风格。我们可以使用抽象工厂模式来处理这种情况。

首先,定义界面元素的抽象类(或接口):

1
2
3
4
5
6
7
8
9
public interface IButton
{
    void Paint();
}

public interface ITextbox
{
    void Paint();
}

接下来,为每种样式定义具体的实现类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Windows风格的实现
public class WindowsButton : IButton
{
    public void Paint()
    {
        Console.WriteLine("Rendering a button in Windows style.");
    }
}

public class WindowsTextbox : ITextbox
{
    public void Paint()
    {
        Console.WriteLine("Rendering a textbox in Windows style.");
    }
}

// MacOS风格的实现
public class MacOSButton : IButton
{
    public void Paint()
    {
        Console.WriteLine("Rendering a button in MacOS style.");
    }
}

public class MacOSTextbox : ITextbox
{
    public void Paint()
    {
        Console.WriteLine("Rendering a textbox in MacOS style.");
    }
}

然后,定义抽象工厂接口和具体工厂类:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public interface IGUIFactory
{
    IButton CreateButton();
    ITextbox CreateTextbox();
}

public class WindowsFactory : IGUIFactory
{
    public IButton CreateButton()
    {
        return new WindowsButton();
    }

    public ITextbox CreateTextbox()
    {
        return new WindowsTextbox();
    }
}

public class MacOSFactory : IGUIFactory
{
    public IButton CreateButton()
    {
        return new MacOSButton();
    }

    public ITextbox CreateTextbox()
    {
        return new MacOSTextbox();
    }
}

最后,客户端代码可以根据需要创建不同的工厂,从而生成不同风格的界面元素:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Client
{
    private IButton _button;
    private ITextbox _textbox;

    public Client(IGUIFactory factory)
    {
        _button = factory.CreateButton();
        _textbox = factory.CreateTextbox();
    }

    public void Paint()
    {
        _button.Paint();
        _textbox.Paint();
    }
}

// 在应用程序入口点选择需要的工厂
class Program
{
    static void Main(string[] args)
    {
        IGUIFactory factory = new WindowsFactory(); // 或 MacOSFactory
        Client client = new Client(factory);
        client.Paint();
    }
}

在这个示例中,IGUIFactory 接口充当抽象工厂,WindowsFactoryMacOSFactory 充当具体工厂,IButtonITextbox 接口定义了产品族,而 WindowsButtonWindowsTextboxMacOSButtonMacOSTextbox 充当具体产品。通过这种方式,我们可以很容易地增加新的产品族(比如Linux风格的界面元素),只需添加相应的工厂和产品实现即可,无需修改现有代码。

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus