一、定义
使用工厂模式的目的是封装对象的创建,属于创建型设计模式,它有三个变种:简单工厂、工厂方法、抽象工厂。
1、简单工厂
有些人不认为它是工厂模式。下面就是一个简单工厂的示例。SimplePizzaFactory类只负责创建产品Pizza。通过入参type创建不同的产品。而Pizza是一个超类,它可以有多个子类。
public class SimplePizzaFactory {
public static Pizza createPizza(String type) {
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new CheesePizza();
} else if (type.equals("calm")) {
pizza = new CalmPizza();
} else if (type.equals("veggle")) {
pizza = new VegglePizza();
}
return pizza;
}
}
2、工厂方法
定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。。
工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。
abstract Product factoryMethod(String type);
- 工厂方法是抽象abstract的,所以依赖子类来处理对象的创建。
- 工厂方法必须返回一个产品Product。超类中定义的方法,通常使用到工厂方法的返回值。比如orderPizza()方法中使用createPizza()这个工厂方法返回的Pizza实例。
- 工厂方法将客户(也就是超类中的代码,例如orderPizza())和实际创建具体产品的代码分割开来。
- 工厂方法也可能需要参数(也可能不需要)来指定所要的产品。
让我们来看看这些类图,以了解有哪些组成元素。
工厂方法和创建者不一定总是抽象的。可以定义一个默认的工厂方法来产生某些具体的产品。这么一来,即使创建者没有任何子类,依然可以创建产品。
3、抽象工厂
定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
让我们看看类图来了解其中的关系:
| 模式 | 优点 | 缺点 | 区别 | 实现 |
|---|---|---|---|---|
| 简单工厂 | 违反对修改关闭原则。要新增\删除产品时,需要到工厂的创建产品方法中修改代码 | |||
| 工厂方法 | 1. 遵循对修改关闭,对扩展开放的原则。 | 1. 使用继承。2. 创建一个产品。 | 利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法,通过子类来创建对象。 | |
| 抽象工厂 | 1. 可以把一群相关的产品集合起来 | 要扩展相关的产品,必须改变接口以及所有子类 | 1. 通过对象的组合。2. 创建整个产品家族。 | 提供一个用来创建一个产品家族的抽象类型(也就是抽象工厂),这个工厂的子类定义了产生产品的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。 |
1、工厂模式的优点
- 将创建对象的代码集中在一个对象或方法中,可以避免代码的重复。
- 代码易于维护和管理。
- 将客户程序从具体类解耦。客户在实例化对象时,只会依赖于接口,而不是具体类。
- 代码具有弹性,可以应对未来的扩展。
2、使用到的OO设计原则
- 封装变化
- 多用组合,少用继承
- 针对接口编程,不针对实现编程
- 为交互对象之间的松耦合设计而努力
- 类应该对扩展开放,对修改关闭
- 依赖倒置原则
二、使用场景
- 当需要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂模式。
- 把客户的代码从需要实例化的具体类中解耦时,使用工厂方法模式。
- 如果目前还不知道将来需要实例化哪些具体类时,使用工厂方法模式。
具体应用
华晟项目管理系统中,在创建项目时,需要同步创建不同的计划。 在创建项目的类型不同时,同步创建的计划也不同。
- 创建常规项目时,需要创建计划有:主计划、生产交付计划、验收计划、SOP计划。
- 创建部门项目时,需要创建计划有:主计划。
- 在项目的验收阶段,需要创建结算计划。