Zer0e's Blog

设计模式之抽象工厂模式

字数统计: 1.2k阅读时长: 5 min
2020/08/13 Share

前言

说实话,就算是假期,每日一到两篇的更新还是有点累的,写一篇长一点的文章差不多一个下午就过去了,但是我个人觉得写文章比较适合我学习,变写的同时能知道哪些不懂,顺便再去复习一下,也算是个不错的方式吧。
今天就来聊聊抽象工厂模式。

正文

概念

之前我们讲过工厂模式,工厂模式的特点是对象的创建交给工厂来实现,隐藏内部逻辑,但是工厂模式也有相应的缺点,那就是一个工厂只能生产一类产品,但往往一个工厂需要有创建多种商品的功能,而抽象工厂模式就是为了解决这个问题。
抽象工厂模式简单说就是一个大工厂下有几个小工厂,小工厂实现大工厂的所有产品。它解决的就是工厂模式下,每个工厂只能创建一类产品的缺点。

实现

就从上次的工厂模式的案例说起,现在一个工厂既可以生产游戏,又可以生产周边,我们就从这个例子来实现抽象工厂模式。
首先是游戏接口及其实体类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface Game {
void test();
}
public class GameA implements Game{
@Override
public void test() {
System.out.println("this is Game A");
}
}
public class GameB implements Game{
@Override
public void test() {
System.out.println("this is Game B");
}
}
public class GameC implements Game{
@Override
public void test() {
System.out.println("this is Game C");
}
}

接下来创建周边接口及其实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public interface Hobby {
public void test();
}
public class HobbyA implements Hobby{
@Override
public void test() {
System.out.println("this is HobbyA");
}
}
public class HobbyB implements Hobby{
@Override
public void test() {
System.out.println("this is HobbyB");
}
}
public class HobbyC implements Hobby{
@Override
public void test() {
System.out.println("this is HobbyC");
}
}

接下来是创建一个抽象工厂

1
2
3
4
public abstract class AbstractFactory {
public abstract Game getGame(String name);
public abstract Hobby getHobby(String name);
}

创建两个工厂继承抽象工厂

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
40
41
42
43
44
public class GameFactory extends AbstractFactory{
public Game getGame(String name){
if (name == null){
return null;
}

if (name.equalsIgnoreCase("GameA")){
return new GameA();
}else if (name.equalsIgnoreCase("GameB")){
return new GameB();
}else if (name.equalsIgnoreCase("GameC")){
return new GameC();
}
return null;
}

@Override
public Hobby getHobby(String name) {
return null;
}
}

public class HobbyFactory extends AbstractFactory{
@Override
public Game getGame(String name) {
return null;
}

@Override
public Hobby getHobby(String name) {
if (name == null){
return null;
}

if (name.equalsIgnoreCase("HobbyA")){
return new HobbyA();
}else if (name.equalsIgnoreCase("HobbyB")){
return new HobbyB();
}else if (name.equalsIgnoreCase("HobbyC")){
return new HobbyC();
}
return null;
}
}

接下来是创建工厂生成器来获取相应的工厂

1
2
3
4
5
6
7
8
9
10
public class FactoryBuilder {
public static AbstractFactory getFactory(String factoryName){
if (factoryName.equalsIgnoreCase("Game")){
return new GameFactory();
}else if (factoryName.equalsIgnoreCase("Hobby")){
return new HobbyFactory();
}
return null;
}
}

创建客户端进行调用

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Client {
public static void main(String[] args) {
AbstractFactory gameFactory = FactoryBuilder.getFactory("Game");
AbstractFactory hobbyFactory = FactoryBuilder.getFactory("Hobby");

Game game = gameFactory.getGame("GameA");
game.test();

Hobby hobby = hobbyFactory.getHobby("HobbyC");
hobby.test();

}
}

以上我们就简单实现了抽象工厂模式,其实原理还是很简单的。

后续思考

当抽象工厂模式中,产品只有一个的时候,抽象工厂模式就是工厂模式,反过来,当产品由一个变多个时,工厂模式变为抽象工厂模式。
那在抽象工厂模式中,添加一个工厂需要怎么操作呢?
很简单,我们只需要创建一个继承于AbstractFactory的工厂就可以了。
那添加一个新的产品呢?
首先当然需要添加一个新的接口与对应的实现类,其次抽象工厂中,需要添加该产品,导致所有继承于抽象类的工厂都必须添加这个产品,只是可以不生产而已,代码上的话,如果工厂很多,就需要添加这些工厂中的重写方法。

优缺点

抽象工厂模式的优点在于解决工厂模式中只能创建单一产品的缺点。并且拥有工厂模式的优点。
而缺点在于产品的扩展较为麻烦,上文提到,添加产品,需要修改抽象类,又需要在实现的工厂中增加代码。

总结

本文简单谈了谈抽象工厂模式,这个模式在开发中很少用到,对整体的架构不利于扩展,修改的话又十分麻烦。工厂模式对于框架的设计还是较为常用的,比如spring的getBean,又如java中的线程池(可以看看线程池的文章),等等很多例子。总之这个工厂模式还是比较重要的。

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 概念
    2. 2.2. 实现
    3. 2.3. 后续思考
    4. 2.4. 优缺点
  3. 3. 总结