1.工厂模式
1.1.为何要有工厂模式
在日常开发中,凡是需要生成复杂对象的地方,都可以尝试考虑使用工厂模式来代替。
注意:上述复杂对象指的是类的构造函数参数过多等对类的构造有影响的情况,因为类的构造过于复杂,如果直接在其他业务类内使用,则两者的耦合过重,后续业务更改,就需要在任何引用该类的源代码内进行更改,光是查找所有依赖就很消耗时间了,更别说要一个一个修改了。
1.2.定义和分类
工厂模式的定义:定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
工厂模式可以分为三类:
- 简单工厂模式(Simple Factory)
- 工厂方法模式(Factory Method)
- 抽象工厂模式(Abstract Factory)
这三种模式从上到下逐步抽象,并且更具一般性。《设计模式》一书中将工厂模式分为两类:工厂方法模式与抽象工厂模式。将简单工厂模式看为工厂方法模式的一种特例,两者归为一类。
2.简单工厂模式
2.1.定义
简单工厂模式又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
在简单工厂模式中,可以根据参数的不同返回不同类的实例。简单工厂专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。
简单工厂模式不属于23种GoF设计模式之一。学习简单工厂模式是学习其它工厂模式的前提条件。
2.2.结构与模式
简单工厂模式的主要角色如下:
- 简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
- 抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
- 具体产品(ConcreteProduct):是简单工厂模式的创建目标。
简单工厂模式结构图:
2.3.代码实现
// 产品抽象接口
public interface Product {
void show();
}
// 具体产品1
public class ConcreteProduct1 implements Product {
@Override
public void show() {
System.out.println("this is ConcreteProduct1");
}
}
// 具体产品2
public class ConcreteProduct2 implements Product {
@Override
public void show() {
System.out.println("this is ConcreteProduct2");
}
}
// 工厂类
public class SimpleFactory {
public Product makeProduct(ProductType t) throws UnsupportedProductException {
switch (t) {
case PRO_1:
return new ConcreteProduct1();
case PRO_2:
return new ConcreteProduct2();
default:
throw new UnsupportedProductException("不支持的产品类型。");
}
}
}
// 产品类型
public enum ProductType {
PRO_1,PRO_2,PRO_3
}
// 不支持产品类型异常
public class UnsupportedProductException extends Exception {
public UnsupportedProductException(String message) {
super(message);
}
}
客户端代码
@Test
public void test() throws Exception {
// 此处工厂创建可使用单例模式实现
SimpleFactory factory = new SimpleFactory();
Product p1 = factory.makeProduct(ProductType.PRO_1);
p1.show();
Product p2 = factory.makeProduct(ProductType.PRO_2);
p2.show();
Product p3 = factory.makeProduct(ProductType.PRO_3);
p3.show();
}
结果输出
this is ConcreteProduct1
this is ConcreteProduct2
org.example.simple_factory.UnsupportedProductException: 不支持的产品。
3.应用场景
3.1.优点和缺点
优点:
- 工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
- 客户端无需知道所创建具体产品的类名,只需知道参数即可。
- 也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点:
- 简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
- 使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
- 系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂 简单工厂模式使用了 static
- 工厂方法,造成工厂角色无法形成基于继承的等级结构。
3.2.应用场景
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。