概念定义

简单工厂(Simple Factory)模式,又称静态工厂方法(Static Factory Method)模式,即定义一个工厂类,根据传入的不同参数创建不同的产品实例,这些实例对象具有共同的父类或接口。

应用场景

  • 需要创建的产品对象较少,否则工厂逻辑会过于复杂。
  • 客户端只关心产品的接口,而不关心对象的具体创建过程。

示例代码

简单工厂模式由一个工厂类、一个产品接口(或抽象类)和一组实现该接口的具体产品组成。这个工厂类根据传入的参数创造一个具体的产品实现类,并向上转型为接口作为结果返回。

本节通过一个"喜闻乐见"的豪车系列,展示简单工厂模式的实现。示例代码如下:

// 产品接口 //
public interface ICar { // 抽象类无法多重继承,而接口支持多实现,扩展性更好
void drive();
}
// 若干具体的产品 //
public class Bmw implements ICar {
@Override
public void drive() { System.out.println("drive a Bmw"); }
}
public class Benz implements ICar {
@Override
public void drive() { System.out.println("drive a Benz"); }
}
public class Audi implements ICar {
@Override
public void drive() { System.out.println("drive a Audi"); }
}
// 工厂类 //
public class SimpleFactory {
private SimpleFactory() {}
public static ICar create(String car) { // 工厂不需要有状态,因此创造产品的方法是静态的
if ("Bmw".equalsIgnoreCase(car)) {
return new Bmw(); // 后续可在工厂里变更产品类名、构造方法参数甚至实例化方式
} else if ("Benz".equalsIgnoreCase(car)) {
return new Benz();
} else if("Audi".equalsIgnoreCase(car)) {
return new Audi();
} else {
return null;
}
}
}

客户端通过SimpleFactory.create("BMW").drive()即可创建Bmw实例并调用其drive()方法。

如注释所示,工厂类封装了产品对象的创建过程,从而可在客户端不感知的情况下修改产品的创建方式。例如,若产品类实现了Cloneable接口,就可以在工厂中用(ICar)Bmw.clone()替代new Bmw()

此外,还可以通过枚举甚至注解实现简单工厂模式。以枚举实现为例:

public enum EnumCarFactory {
BMW {
@Override
public ICar create() { return new Bmw(); }
},
BENZ {
@Override
public ICar create() { return new Benz(); }
},
AUDI {
@Override
public ICar create() { return new Audi(); }
}; public abstract ICar create(); // abstract修饰方法,强制每个枚举实现该方法
}

客户端通过EnumCarFactory.AUDI.create().drive()EnumCarFactory.valueOf("AUDI").create().drive(),即可创建Audi实例并调用其draw()方法。

注意,以上实现并不符合开放-封闭原则(对扩展开放,对修改关闭)。例如新增产品时,SimpleFactory工厂内需要添加分支条件,EnumCarFactory工厂内则要添加对应的枚举定义。这一缺陷可以通过反射机制来避免:

public class EnhancedSimpleFactory {
private EnhancedSimpleFactory() {}
public static <T> T create(Class<? extends T> clazz) {
T obj = null;
try {
obj = (T) Class.forName(clazz.getName()).newInstance();
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return obj;
}
}

客户端通过EnhancedSimpleFactory.create(Benz.class).drive(),即可创建Benz实例并调用其draw()方法。

注意,EnhancedSimpleFactory.create(clazz)的入参类路径也可来自配置文件、数据库等,因此更具灵活性。

模式优缺点

简单工厂模式的优点如下:

  • 解耦:将对象的创建和使用过程分开(客户端只接触产品接口),降低对象和客户端的耦合关系。
  • 降低代码重复: 将创建对象的过程集中于工厂内部,当创建对象较为复杂且频繁创建时,可以减少重复性代码。
  • 降低维护成本:创建过程由工厂统一管理,当业务逻辑变更时在工厂里修改即可,而无需逐个修正所有需要创建对象的地方。

缺点如下:

  • 简单工厂使用静态工厂方法,静态方法不能被继承和重写,因此工厂角色无法形成基于继承的等级结构。
  • 简单工厂容易违背开放-封闭原则(虽然可以通过反射机制改善),可能导致工厂逻辑过于复杂。
  • 工厂类集中负责所有产品对象的创建逻辑,一旦工厂不能正常工作,整个系统都会受到影响。

业界实践

随处可见……

最新文章

  1. WEB三层架构与MVC
  2. Dijkstra 最短路算法(只能计算出一条最短路径,所有路径用dfs)
  3. do break的妙用
  4. 编程实例--for循环,找出0~100之间与8有关的正整数
  5. poj 2155
  6. 设计模式(七)组合模式Composite(结构型)
  7. Appium Android Bootstrap源码分析之控件AndroidElement
  8. JavaScript模板引擎原理
  9. 转自他人——————TLE之前,没有一个节点叫失败!!!
  10. ThinkPHP 分组,应用,跳转
  11. [原创] debian 9.3 搭建Jira+Confluence+Bitbucket项目管理工具(三) -- 安装confluence 6.6.1
  12. DAY11 函数(二)
  13. AndroidStudio 之 Inter x86 Emulator Accelerator(Haxm installer) - not compatible with windows
  14. windows 查询文件被什么程序占用
  15. linux export环境变量
  16. 一个简单的Golang实现的HTTP Proxy
  17. HOJ 1936&POJ 2955 Brackets(区间DP)
  18. 【UVa】11212 Editing a Book(IDA*)
  19. CENTOS 使用 MUTT发送邮件
  20. JS十进制转二进制(控制位数)

热门文章

  1. 2019阿里天猫团队Java高级工程师面试题之第二面
  2. yii2自定义操作按钮
  3. 松软科技web课堂:JavaScript 数组
  4. JS基础语法---对象总结
  5. ebs oracle YTD期间费用
  6. 矩阵的运算:Python语言实现
  7. Swift设置只读(readOnly)属性
  8. 自己写的一个连数据库的音乐调用模块 MusicRj
  9. python3.7安装, 解决pip is configured with locations that require TLS/SSL问题
  10. 004 C/C++ 数据类型_类型别名