Java 设计模式03——抽象工厂模式

模式定义

抽象工厂模式,提供一个创建一系列相关或相互依赖对象的接口,而无需指定他们具体的类;理解起来就是抽象工厂的接口定义中可以有多个接口方法,这些接口方法分别用来创建不同的对象。

模式示例

以台式电脑组装为例,不同的电脑厂商会选用不同的电脑配件,这里的主要配件有CPU、显示器、主板等,不同的品牌采用的不同的配件组装成电脑售卖,当然我们也可以自己组装电脑。这里就简单列出几个品牌,如惠普、苹果以及自己组装。这三个品牌对应的就是三个具体的工厂。

  1. 定义好配件,如CPU、显示器、主板等;
  2. 定义好抽象工厂,即创建CPU、创建显示器和创建主板;
  3. 定义好具体工厂,即华为电脑工厂、苹果电脑工厂;
  4. 示例检验客户端定义。

具体代码

配件的定义

CPU基类

Cpu.java

1
2
3
public abstract class Cpu {
public abstract String cpuName();
}

HuaweiCpu.java

1
2
3
4
5
6
public class HuaweiCpu extends Cpu {
@Override
public String cpuName() {
return "华为自研芯片";
}
}

XiaoLongCpu.java

1
2
3
4
5
6
public class XiaoLongCpu extends Cpu {
@Override
public String cpuName() {
return "骁龙855芯片";
}
}

显示器基类

Monitor.java

1
2
3
public abstract class Monitor {
public abstract String monitorName();
}

RetinaMonitor.java

1
2
3
4
5
6
7
public class RetinaMonitor extends Monitor {

@Override
public String monitorName() {
return "Retina显示器";
}
}

PhilipsMonitor.java

1
2
3
4
5
6
7
public class PhilipsMonitor extends Monitor {

@Override
public String monitorName() {
return "飞利浦显示器";
}
}

主板基类

MainBoard.java

1
2
3
public abstract class MainBoard {
public abstract String mainBoardName();
}

AsusMainBoard.java

1
2
3
4
5
6
public class AsusMainBoard extends MainBoard {
@Override
public String mainBoardName() {
return "华硕主板";
}
}

GigaMainBoard.java

1
2
3
4
5
6
public class GigaByteMainBoard extends MainBoard {
@Override
public String mainBoardName() {
return "技嘉主板";
}
}

定义抽象工厂

ComputerFactory.java,代表抽象的电脑生成线。

1
2
3
4
5
6
7
8
9
10
11
12
public abstract class ComputerFactory {
public abstract Cpu createCpu();

public abstract MainBoard createMainBoard();

public abstract Monitor createMonitor();

public void computerInfo() {
System.out.println("生产的电脑型号描述:CPU->" + createCpu().cpuName() +
", 主板->" + createMainBoard().mainBoardName() + ", 显示器->" + createMonitor().monitorName());
}
}

定义具体的工厂

AppleComputerFactory.java,代表苹果电脑生产线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AppleComputerFactory extends ComputerFactory {

@Override
public Cpu createCpu() {
return new A14Cpu();
}

@Override
public MainBoard createMainBoard() {
return new GigaByteMainBoard();
}

@Override
public Monitor createMonitor() {
return new RetinaMonitor();
}
}

HuaweiComputerFactory.java,代表华为电脑生产线。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class HuaweiComputerFactory extends ComputerFactory {

@Override
public Cpu createCpu() {
return new HuaweiCpu();
}

@Override
public MainBoard createMainBoard() {
return new AsusMainBoard();
}

@Override
public Monitor createMonitor() {
return new PhilipsMonitor();
}
}

定义示例客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class AbsFactoryClient {
public static void main(String[] args) {
ComputerFactory computerFactory = new AppleComputerFactory();

computerFactory.computerInfo();

ComputerFactory computerFactory1 = new HuaweiComputerFactory();

computerFactory1.computerInfo();

}
}
// 输出结果
生产的电脑型号描述:CPU->苹果A14放生芯片, 主板->技嘉主板, 显示器->Retina显示器
生产的电脑型号描述:CPU->华为自研芯片, 主板->华硕主板, 显示器->飞利浦显示器

模式总结

通过比较抽象工厂模式和工厂方法模式,你会发现抽象工厂模式中工厂的实现类中提供了创建不同对象的方法,这些不同的对象间存在着一种外在的联系,如本例中同一个工厂中穿件的对象属于一条电脑生产线上的。如果我们要为电脑生产线增加键盘这种流水化操作,那么我们同样需要修改所有的工厂类,但是如果我们要开辟一条新的生产线,我们就不用动原来的代码,而是直接将这个生产线(具体工厂类)定义出来即可。可见抽象工厂模式有如下特点:

  1. 改变生产线同样会违背“开闭原则”,新增生产线可以不需要修改代码,符合“开闭原则”;
  2. 不用关心对象的创建过程,改变生产线中某个配件就十分方便。