创建型设计模式的一种

简单工厂模式

在说工厂模式之前,先说一下简单工厂模式。

简单工厂模式是为了避免在客户端调用时判断各种复杂逻辑,所有的都放到单独的简单工厂类中处理。

简单工厂模式举例

假设数据模型分两种,二维模型(TwoDimModel)和多维模型(MultiDimModel),各自的处理方式不同,于是客户端需要有如下调用方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main {
public static void main() {
// 处理模型的服务接口
IService srv = null;
Model model = new TwoDimModel();
// Model model = new MultiDimModel();
if ("two-dim".equals(model.getModelType())) {
srv = new TwoDimService();
} else if ("multi-dim".equals(model.getModelType())) {
srv = new MultiDimService();
}
// 执行操作
srv.operate();
}
}

可以看到,这样就把获取服务的代码和调用方法的代码混在一起了,而且如果很多地方都需要调用IService服务,就会造成很多代码重复,同时会导致维护和修改困难。那么就可以使用简单工厂模式,将获取服务的代码放在工厂类中,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 工厂类
*/
public class ServiceFactory {
public static IService createService(String modelType) {
IService srv = null;
if ("two-dim".equals(modelType)) {
srv = new TwoDimService();
} else if ("multi-dim".equals(modelType)) {
srv = new MultiDimService();
}
return srv;
}
}
/**
* 客户端类
*/
public class Main {
public static void main() {
Model model = new TwoDimModel();
// Model model = new MultiDimModel();

// 处理模型的服务接口
IService srv = ServiceFactory.createService(model.getModelType());
// 执行操作
srv.operate();
}
}

这样在获取服务的地方只需要使用ServiceFactory的create方法即可,客户端不需要关注具体是哪个service。

简单工厂模式类图

简单工厂模式类图

该模式的精髓是工厂类的create方法,一般是静态方法。

简单工厂模式的局限

当我们增加模型的种类,比如加一个三维模型(非多维模型),那么需要做两件事:1. 增加模型类;2. 在工厂方法中增加if判断。 但是在工厂方法中修改就不满足“开闭原则”了,因为是对修改的是关闭的。所以需要引入下面的工厂模式。

工厂模式实现上述举例

工厂模式实现上述举例,只需要将工厂类抽象成接口,然后对每一个服务分别创建工厂方法,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 工厂接口
*/
public interface IFactory {
IService createService();
}
/**
* 二维模型服务工厂
*/
public class TwoDimSrvFactory implements IFactory{
@Override
public IService createService() {
return new TwoDimService();
}
}
/**
* 多维模型服务工厂
*/
public class MultiDimSrvFactory implements IFactory{
@Override
public IService createService() {
return new MultiDimService();
}
}
/**
* 客户端类
*/
public class Main {
public static void main() {
Model model = new TwoDimModel();
// Model model = new MultiDimModel();
// 服务工厂
IFactory factory = new TwoDimSrvFactory();
// 处理模型的服务接口
IService srv = factory.createService();
// 执行操作
srv.operate();
}
}

这样在增加一种模型的时候,同样需要做两件事: 1. 创建模型类;2. 创建模型服务的工厂类。这样就避免了在简单工厂方法中对工厂类的侵入和修改。

但是很明显,这又把对模型的判断放到了客户端调用位置,因此在增加模型的时候会对客户端类进行大量的修改。这就需要简单工厂模式+抽象工厂模式来更好的解决。

工厂模式类图

工厂模式类图

该类图的核心是创建工厂接口,不同的服务使用对应的工厂方法创建。

工厂模式【DP】定义

定义一个用于创建对象的接口(上述的IFactory解耦),让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。

工厂模式使用场景

  1. 希望工厂与产品的种类对客户端保持透明,给客户端提供一致的操作
  2. 不同的工厂和产品可以提供客户端不同的服务或功能

工厂模式注意事项

  1. 简单工厂模式和工厂模式都是从一堆产品(服务、模型等)中选择一个使用,工厂模式中的不同的具体工厂类还能提供一些其他功能,从代码隔离角度来说,如果除了获取某一个产品,还需要一些复杂的逻辑实现,那么使用工厂方法更好一些,反之,如果只需要获取某个产品,那使用简单工厂即可。
  2. 再次强调: 使用工厂模式,在客户端调用仍然会使用一些判断,将服务类型判断和客户端调用混在一起,做不到无侵入地增加产品,比较好的方法见简单工厂模式+抽象工厂模式.