1. 工厂方法模式的定义
在简单工厂模式文中,阐述了简单工厂模式的缺点:
- 扩展性受限:如果需要添加新的产品类型,通常需要修改工厂类的逻辑,违反了开闭原则。
- 责任过重:工厂类负责创建多种产品,导致工厂类代码可能会变得非常庞大。
- 违反单一职责原则:工厂类不仅负责对象的创建,还可能包括其它业务逻辑,违反了单一职责原则。
- 静态方法限制: 静态方法不支持多态,无法通过继承扩展行为
工厂方法模式可以解决上述问题。
工厂方法模式是创建型设计模式 ,核心思想是将对象创建延迟到子类,通过多态机制实现产品族的动态扩展。 。通过定义创建对象的抽象方法,让子类决定具体实例化哪个类,完美遵循开闭原则(对扩展开放,对修改关闭)。
解决的核心问题:
- 动态扩展瓶颈:当系统需要支持新产品时,简单工厂需修改工厂类代码
- 创建逻辑定制化:不同场景需要不同的对象创建策略
- 框架级扩展:允许框架用户定义自己的产品实现
核心机制:
java
abstract class Creator {
// 工厂方法 - 延迟到子类实现
protected abstract Product factoryMethod();
// 模板方法
public final void businessLogic() {
Product product = factoryMethod(); // 运行时多态调用
product.operation();
}
}
2. 工厂方法模式的结构
工厂方法模式主要包含以下角色:
- Creator(抽象创建者):定义工厂方法接口,包含调用工厂方法的业务逻辑。
- ConcreteCreator(具体创建者):实现工厂方法,负责创建具体产品。
- Product(抽象产品):定义产品的接口。
- ConcreteProduct(具体产品):实现产品接口的具体类。
txt
Creator (抽象)
|
|-- factoryMethod() : Product
|-- businessLogic()
|
ConcreteCreator --> ConcreteProduct
|
Product (抽象)
|
ConcreteProduct
特点:
- 每个具体工厂负责创建一种具体产品。
- 客户端通过抽象工厂接口使用,不依赖具体实现。
- 新增产品类型时,只需新增对应的工厂子类。
2.1 Creator 抽象创建者
java
public abstract class ShapeFactory {
// 工厂方法 - 延迟到子类实现
protected abstract Shape createShape();
public final void render() {
Shape shape = createShape();
System.out.println("开始渲染图形:");
shape.draw();
System.out.println("渲染完成");
}
}
2.2 Product 抽象产品
java
public interface Shape {
void draw();
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形 ○");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("绘制正方形 □");
}
}
2.3 ConcreteCreator 具体创建者
java
public class CircleFactory extends ShapeFactory {
@Override
protected Shape createShape() {
return new Circle();
}
}
public class SquareFactory extends ShapeFactory {
@Override
protected Shape createShape() {
return new Square();
}
}
2.4 Client 客户端
java
public class Client {
public static void main(String[] args) {
// 创建圆形
ShapeFactory circleFactory = new CircleFactory();
circleFactory.render();
// 创建正方形
ShapeFactory squareFactory = new SquareFactory();
squareFactory.render();
}
}
3. 工厂方法模式的优缺点
优点:
- 符合开闭原则:新增产品类型时,只需新增工厂子类,无需修改现有代码。
- 降低耦合度:客户端不直接依赖具体产品类,而是依赖抽象。
- 单一职责:每个工厂只负责创建一种产品。
- 支持扩展:可以方便地添加新的产品类型。
缺点:
- 类的数量增加:每增加一个产品,就需要增加一个对应的工厂类。
- 增加系统复杂度:引入了额外的抽象层。
- 理解成本:相比直接创建对象,需要理解工厂层次结构。
4. 工厂方法模式的设计思想
- 延迟实例化:将对象创建延迟到子类中进行。
- 多态性:通过继承和多态实现不同产品的创建。
- 模板方法:在抽象类中定义算法骨架,具体步骤由子类实现。
- 依赖倒置:高层模块不依赖低层模块,都依赖于抽象。
5. 一些问题
Q1: 工厂方法模式与简单工厂模式的区别是什么?
A1:
- 简单工厂模式:用一个工厂类创建所有产品,新增产品需要修改工厂类
- 工厂方法模式:每个产品对应一个工厂类,新增产品只需新增工厂类
- 核心区别:简单工厂违反开闭原则,工厂方法符合开闭原则
java
// 简单工厂:集中创建,需要修改工厂类
class SimpleFactory {
public static Shape createShape(String type) {
switch (type) {
case "circle": return new Circle();
case "square": return new Square();
// 新增产品需要修改这里
default: throw new IllegalArgumentException();
}
}
}
// 工厂方法:分散创建,新增工厂子类
abstract class ShapeFactory {
abstract Shape createShape();
}
class CircleFactory extends ShapeFactory { /* ... */ }
class SquareFactory extends ShapeFactory { /* ... */ }
// 新增产品只需新增工厂类
Q2: 工厂方法模式在什么场景下不适用?
-
产品类型固定且简单
- 解释:如果产品类型很少且不会变化,使用简单工厂或直接创建更合适。
- 例子:只有2-3种固定的配置对象,且未来不会扩展。
-
性能要求极高
- 解释:工厂方法涉及虚方法调用和继承层次,有轻微性能开销。
- 例子:游戏引擎中的高频对象创建,每毫秒创建数千个对象。
-
简单的一次性使用
- 解释:如果对象只在一个地方创建和使用,工厂模式会增加不必要的复杂性。
- 例子:临时的数据传输对象或简单的值对象。
-
类爆炸问题严重
- 解释:每个产品都需要对应的工厂类,可能导致类数量翻倍。
- 例子:有50种产品类型,就需要50个工厂类,维护成本高。