工厂方法模式
1. 问题提出:简单工厂的局限性
-
回顾开闭原则 (OCP)
- 核心: 软件实体应该是可扩展的,而不可修改的。即对扩展是开放的,对修改是封闭的。
- 目标: 软件设计本身所追求的目标就是封装变化、降低耦合。
- 方法论: 为了应对“需求总是变化”这一事实,软件设计者必须找到一种方法,在不修改原有系统的基础上进行功能扩展。这个方法的关键就是依赖于抽象。
-
简单工厂模式的问题
- 我们来看一个使用简单工厂的图表(Chart)生成案例。
ChartFactory类根据传入的字符串类型(“histogram”, “pie” 等)来创建并返回不同的图表对象(HistogramChart,PieChart)。
- 我们来看一个使用简单工厂的图表(Chart)生成案例。

UML图展示了一个
ChartFactory,它依赖于多个具体图表类。代码展示了ChartFactory内部的switch-case结构。
- 新需求: 用户要求系统支持一种新的图表,例如“点状图”(DotChart)。
- 现有做法: 为了支持这个新产品,我们必须修改
ChartFactory类的源代码,在switch-case结构中增加一个新的case分支来创建DotChart对象。 - 结论: 这种做法修改了已有的类,明显违背了开闭原则。每次增加新产品,都需要修改工厂类,这使得工厂类变得不稳定且难以维护。
2. 模式动机
- 核心动机: 解决简单工厂模式在增加新产品时违反“开闭原则”的问题。
- 解决方案: 将原来集中在一个工厂类中的对象创建逻辑,分散到各个子类中去。具体做法是:
- 定义一个抽象工厂类 (Abstract Factory):这个抽象工厂类中定义了一个用于创建产品的抽象方法(即“工厂方法”)。
- 创建具体工厂类 (Concrete Factory):每一种需要被创建的产品,都对应一个专门的“具体工厂类”。这个具体工厂类会继承自抽象工厂类,并重写(实现)那个抽象的工厂方法,使其返回对应的具体产品实例。
- 达到的效果: 这种抽象化的结果使得整个结构可以在不修改已有具体工厂类的情况下,通过增加新的具体工厂类来引入新的产品。扩展时,只需要增加一个新的产品类和一个与之对应的新的工厂类即可,完全符合开闭原则。

图片描述:左图是一个“按钮工厂”,集中生产多种按钮,增加新按钮时必须修改工厂。 右图是一个“抽象按钮工厂”体系,每个具体按钮(矩形、圆形等)都有一个自己的具体工厂,增加“椭圆形按钮”时,只需增加一个新的“椭圆形按钮工厂”即可,原有结构不变。
3. 模式定义
- 定义: 工厂方法模式 (Factory Method Pattern) 定义了一个用于创建对象的接口(抽象方法),让子类决定实例化哪一个类。
- 核心思想: 在工厂方法模式中,父类负责定义创建对象的公共接口(抽象工厂方法),而子类则负责生成具体的对象。这样做的目的是将类的实例化操作延迟到子类中完成。
- 分类: 工厂方法模式属于类创建型模式。
4. 结构及角色分析
工厂方法模式包含四个核心角色:

该UML图,包含Product和Creator两个平行的继承体系、每个角色的名称和职责。
-
Product (抽象产品)
- 定义: 是一个抽象类或接口,定义了工厂方法所创建的对象的公共接口。
-
ConcreteProduct (具体产品)
- 定义: 继承或实现
Product接口,是工厂方法模式所创建的最终对象。 - 它重写(实现)基类的抽象方法。
- 定义: 继承或实现
-
Creator (抽象工厂)
- 定义: 是一个抽象类或接口,它声明了用于创建产品的“工厂方法”
factoryMethod()。 - 该方法的返回类型是抽象产品类型
Product。 Creator也可以包含其他依赖于Product抽象的业务方法。
- 定义: 是一个抽象类或接口,它声明了用于创建产品的“工厂方法”
-
ConcreteCreator (具体工厂)
- 定义: 继承或实现
Creator接口,是实际创建产品的类。 - 它重写(实现)
factoryMethod(),返回一个具体的ConcreteProduct实例。
- 定义: 继承或实现
-
代码结构示例:
// 伪代码示例
// --- 产品层次结构 ---
interface Product {
void use();
}
class ConcreteProduct implements Product {
@Override
public void use() {
// 具体产品的实现
}
}
// --- 工厂层次结构 ---
abstract class Creator {
// 声明工厂方法,返回抽象产品
public abstract Product factoryMethod();
public void someOperation() {
// 调用工厂方法创建产品
Product product = factoryMethod();
// ... 使用产品
product.use();
}
}
class ConcreteCreator extends Creator {
// 重写工厂方法,返回具体产品
@Override
public Product factoryMethod() {
return new ConcreteProduct();
}
}
1307

被折叠的 条评论
为什么被折叠?



