需求
创建对象时,通过提供一个通用接口来隐藏内部细节。这样将对象的实例化与使用分离,使得用户无需了解具体参数就能创建所需的产品类,从而避免在客户端代码中直接指定实现细节,达到解耦的目的。
类图
核心组成
| 组成(角色) | 关系 | 作用 |
|---|---|---|
| 抽象产品(Product) | 具体产品的父类 | 描述产品的公共接口 |
| 具体产品(Concrete Product) | 抽象产品的子类;工厂类创建的目标类 | 描述生产的具体产品 |
| 工厂(Creator) | 被外界调用 | 根据传入不同参数从而创建不同具体产品类的实例 |
代码实现
Product 接口
public interface Product {
String getProductName();
}
具体实现类
具体实现类 A
public class ConcreteProductA implements Product{
@Override
public String getProductName() {
return "Product A";
}
}
具体实现类 B
public class ConcreteProductB implements Product{
@Override
public String getProductName() {
return "Product B";
}
}
具体实现 C
public class ConcreteProductC implements Product{
@Override
public String getProductName() {
return "Product C";
}
}
简单工厂类
public class SimpleFactory {
public Product getProductInstance(int flag) {
switch (flag) {
case 1:
return new ConcreteProductA();
case 2:
return new ConcreteProductB();
case 3:
return new ConcreteProductC();
default:
throw new RuntimeException("Not such type of Product:" + flag);
}
}
}
客户端类
package com.jools.designpattern.factory.simplefactory;
public class Client {
public static void main(String[] args) {
SimpleFactory simpleFactory = new SimpleFactory();
Product productInstance = simpleFactory.getProductInstance(1);
System.out.println(productInstance.getProductName());
productInstance = simpleFactory.getProductInstance(2);
System.out.println(productInstance.getProductName());
productInstance = simpleFactory.getProductInstance(3);
System.out.println(productInstance.getProductName());
/*
输出:
Product A
Product B
Product C
*/
}
}
优缺点分析
优点
- 有助于封装: 单工厂实现组件封装,助外部面向接口编程
- 解耦: 实现客户端与具体实现类解耦,客户端不知具体实现情况,只通过工厂获取接口对象。
缺点
- 增加复杂度: 可能增加客户端复杂度,若依参数选实现类,客户端需理解参数含义,可选用可配置方式。
- 不利于扩展: 私有化构造方法后不能通过子类改变创建接口方法行为,通常无需为简单工厂创建子类。
小结
本质
- 简单工厂的本质在于:
选择实现 - 需要重点考虑如何选择,实现基本已经完成
何时使用简单工厂?
-
完全封装具体实现,仅通过接口操作。
-
集中管理和控制对象创建过程。
3. 简单工厂 vs 抽象工厂
-
简单工厂:选择特定实现。
-
抽象工厂:选择一组相关产品的实现。如果抽象工厂只有一个实现,则退化为简单工厂。
4. 简单工厂 vs 工厂方法模式
- 简单工厂:直接在工厂类中选择实现。
- 工厂方法:将选择具体实现的功能延迟到子类完成。