抽象工厂模式
- 1. 模式定义
- 2. 模式结构
- 3. 实现
- 3.1 实现抽象产品接口
- 3.2 定义具体产品
- 3.3 定义抽象工厂接口
- 3.4 定义具体工厂
- 3.5 客户端代码
- 4. 模式分析
- 4.1 抽象工厂模式退化为工厂方法模式
- 4.2 工厂方法模式退化为简单工厂模式
- 5. 模式特点
- 5.1 优点
- 5.2 缺点
- 6. 适用场景
- 6.1 需要创建一组相关或相互依赖的对象
- 6.2 系统不应依赖于产品类的具体实现
- 6.3 需要提供一组产品的多种变体
- 7. 模式扩展
- 7.1 “开闭原则”的倾斜性
- 7.1.1 增加产品族:
- 7.1.2 增加产品等级结构:
1. 模式定义
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。
2. 模式结构
抽象工厂模式包含如下角色:
- AbstractFactory:抽象工厂
- ConcreteFactory:具体工厂
- AbstractProduct:抽象产品
- Product:具体产品
3. 实现
3.1 实现抽象产品接口
首先,定义两个抽象产品接口:Button 和 TextBox。
package main
import "fmt"
// Button 是按钮的抽象接口
type Button interface {
Render()
}
// TextBox 是文本框的抽象接口
type TextBox interface {
Render()
}
3.2 定义具体产品
这些类实现了抽象产品接口。
// WindowsButton 是 Windows 风格的按钮
type WindowsButton struct{}
func (b *WindowsButton) Render() {
fmt.Println("Rendering Windows Button")
}
// MacButton 是 Mac 风格的按钮
type MacButton struct{}
func (b *MacButton) Render() {
fmt.Println("Rendering Mac Button")
}
// WindowsTextBox 是 Windows 风格的文本框
type WindowsTextBox struct{}
func (t *WindowsTextBox) Render() {
fmt.Println("Rendering Windows TextBox")
}
// MacTextBox 是 Mac 风格的文本框
type MacTextBox struct{}
func (t *MacTextBox) Render() {
fmt.Println("Rendering Mac TextBox")
}
3.3 定义抽象工厂接口
声明了创建一组相关对象的方法。
// GUIFactory 是 GUI 工具包的抽象工厂接口
type GUIFactory interface {
CreateButton() Button
CreateTextBox() TextBox
}
3.4 定义具体工厂
这些类实现了抽象工厂接口。
// WindowsFactory 是 Windows 风格的 GUI 工具包工厂
type WindowsFactory struct{}
func (f *WindowsFactory) CreateButton() Button {
return &WindowsButton{}
}
func (f *WindowsFactory) CreateTextBox() TextBox {
return &WindowsTextBox{}
}
// MacFactory 是 Mac 风格的 GUI 工具包工厂
type MacFactory struct{}
func (f *MacFactory) CreateButton() Button {
return &MacButton{}
}
func (f *MacFactory) CreateTextBox() TextBox {
return &MacTextBox{}
}
3.5 客户端代码
使用抽象工厂模式创建一组相关对象。
func main() {
var factory GUIFactory
// 可以根据需要选择不同的工厂
factory = &WindowsFactory{}
// factory = &MacFactory{}
button := factory.CreateButton() //Rendering Windows Button
textBox := factory.CreateTextBox() //Rendering Windows TextBox
button.Render() //Rendering Mac Button
textBox.Render() //Rendering Mac TextBox
}
4. 模式分析
4.1 抽象工厂模式退化为工厂方法模式
- 条件: 每个具体工厂类只创建一个产品对象,即只存在一个产品等级结构。
- 结果: 抽象工厂模式退化为工厂方法模式,因为不再需要创建多个相关的产品对象。
4.2 工厂方法模式退化为简单工厂模式
- 条件: 抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的方法设计为静态方法。
- 结果: 工厂方法模式退化为简单工厂模式,因为所有产品对象的创建都由一个统一的工厂类负责。
5. 模式特点
5.1 优点
- 确保同一产品族的对象一起工作。
- 客户端不需要知道每个对象的具体类,简化了代码。
5.2 缺点
扩展产品族非常困难。增加一个新的产品族需要修改抽象工厂和所有具体工厂的代码。
6. 适用场景
6.1 需要创建一组相关或相互依赖的对象
当系统需要创建一组相关或相互依赖的对象时,抽象工厂模式可以确保这些对象的一致性和兼容性。例如,创建不同风格的 GUI 组件(按钮、文本框等)。
6.2 系统不应依赖于产品类的具体实现
当系统不应依赖于产品类的具体实现,而是通过接口来操作对象时,抽象工厂模式可以提供一个统一的接口来创建对象。
6.3 需要提供一组产品的多种变体
当系统需要提供一组产品的多种变体(如不同平台的 GUI 组件),并且客户端代码需要透明地使用这些变体时,抽象工厂模式是一个合适的选择。
7. 模式扩展
7.1 “开闭原则”的倾斜性
7.1.1 增加产品族:
- 支持良好: 当需要增加新的产品族(例如,不同风格的按钮和文本框)时,只需添加新的具体工厂类和相应的产品类,而无需修改现有的代码。这符合开闭原则,因为系统对扩展开放,对修改封闭。
7.1.2 增加产品等级结构:
- 支持不佳: 当需要增加新的产品等级结构(例如,新增一种产品类型如复选框)时,必须修改抽象工厂接口和所有具体工厂类,添加创建新产品的方法。这违反了开闭原则,因为需要修改现有的代码。