抽象工厂
(Abstract Factory
)模式主要目的是提供一个接口
,用于创建一系列相关或依赖对象的家族
,而无需指定它们具体的类。通过这种方式,一个系统可以独立于它如何创建、组合和表示它的产品,这样系统就只需要知道如何从抽象工厂中获取产品的接口,而无需了解具体的实现细节。
核心组件
抽象工厂模式涉及以下几个核心组件:
- 抽象工厂(Abstract Factory):这是一个接口,声明了一系列创建抽象产品的方法。
- 具体工厂(Concrete Factory):实现抽象工厂接口的具体类。每个具体工厂都能够按照工厂方法模式产生一组具体产品。
- 抽象产品(Abstract Product):为一类产品对象声明一个接口。所有类型的产品对象都要支持这个接口。
- 具体产品(Concrete Product):抽象产品的具体子类。具体工厂负责创建具体产品的实例。
- 客户端(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
接口充当抽象工厂,WindowsFactory
和 MacOSFactory
充当具体工厂,IButton
和 ITextbox
接口定义了产品族,而 WindowsButton
、WindowsTextbox
、MacOSButton
和 MacOSTextbox
充当具体产品。通过这种方式,我们可以很容易地增加新的产品族(比如Linux风格的界面元素),只需添加相应的工厂和产品实现即可,无需修改现有代码。