# 定义
前面介绍的 [工厂模式](https://lixj.fun/archives/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F) 中考虑的是一类产品的生产,如畜牧场只养动物、电视机厂只生产电视机、计算机软件学院只培养计算机软件专业的学生等。
抽象工厂也可以称作其他工厂的工厂,它可以在抽象工厂中创建出其他工厂,与工厂模式一样,都是用来解决接口选择的问题,同样都属于创建型模式。
>同种类称为同等级,也就是说:工厂方法模式只考虑生产同等级的产品,但是在现实生活中许多工厂是综合型的工厂,能生产多等级(种类) 的产品,如农场里既养动物又种植物,电器厂既生产电视机又生产洗衣机或空调,大学既有软件专业又有生物专业等。
## 模式的定义与特点
抽象工厂(AbstractFactory)模式的定义:是一种为访问类提供一个创建一组相关或相互依赖对象的接口,且访问类无须指定所要产品的具体类就能得到同族的不同等级的产品的模式结构。
抽象工厂模式是工厂方法模式的升级版本,工厂方法模式只生产一个等级的产品,而抽象工厂模式可生产多个等级的产品。
使用抽象工厂模式一般要满足以下条件。
- 系统中有多个产品族,每个具体工厂创建同一族但属于不同等级结构的产品。
- 系统一次只可能消费其中某一族产品,即同族的产品一起使用。
抽象工厂模式除了具有工厂方法模式的优点外,其他主要优点如下。
- 可以在类的内部对产品族中相关联的多等级产品共同管理,而不必专门引入多个新的类来进行管理。
- 当需要产品族时,抽象工厂可以保证客户端始终只使用同一个产品的产品组。
- 抽象工厂增强了程序的可扩展性,当增加一个新的产品族时,不需要修改原代码,满足开闭原则。
其缺点是:当产品族中需要增加一个新的产品时,所有的工厂类都需要进行修改。增加了系统的抽象性和理解难度。
本节要介绍的抽象工厂模式将考虑多等级产品的生产,将同一个具体工厂所生产的位于不同等级的一组产品称为一个产品族。
# 实践
这两年新冠疫情期间,防护服和口罩成为我们日常生活中必不可少的东西。
口罩可以分为普通口罩、医用口罩;
防护服可以分为普通防护服、医用防护服;
普通工厂生产普通口罩和普通防护服,医用口罩和医用防护服则由专业工厂生产;

代理结构如下:

首先是产品类的代码,口罩和防护服是两个抽象接口,分别拥有医用和普通两个实现类;
```
public interface IMask {
void showMask();
}
public class OrdinaryMaskImpl implements IMask {
@Override
public void showMask() {
System.out.println("这是普通口罩");
}
}
public class SurgicalMaskImpl implements IMask {
@Override
public void showMask() {
System.out.println("这是医用口罩");
}
}
```
```
public interface IProtectiveSuit {
void showSuit();
}
public class OrdinaryProtectiveSuitImpl implements IProtectiveSuit {
@Override
public void showSuit() {
System.out.println("这是普通防护服");
}
}
public class SurgicalProtectiveSuitImpl implements IProtectiveSuit {
@Override
public void showSuit() {
System.out.println("这是医用防护服");
}
}
```
接下来是工厂类,由于产品分成了医用和普通两大组,工厂也相应分成了专业工厂和普通工厂,各自负责组内产品的创建;
```
public interface IFactory {
IMask createMask();
IProtectiveSuit createProtective();
}
public class OrdinaryFactory implements IFactory {
@Override
public IMask createMask() {
return new OrdinaryMaskImpl();
}
@Override
public IProtectiveSuit createProtective() {
return new OrdinaryProtectiveSuitImpl();
}
}
public class SurgicalFactory implements IFactory {
@Override
public IMask createMask() {
return new SurgicalMaskImpl();
}
@Override
public IProtectiveSuit createProtective() {
return new SurgicalProtectiveSuitImpl();
}
}
```
最后是客户端代码,通过实例化不同的工厂子类,调用不同的创建方法,可以创建出不同的产品。
```
public class TestFactory {
public static void main(String[] args) {
IFactory factory1 = new OrdinaryFactory();
IFactory factory2 = new SurgicalFactory();
IMask mask1 = factory1.createMask();
mask1.showMask();
IProtectiveSuit protectiveSuit1 = factory1.createProtective();
protectiveSuit1.showSuit();
IMask mask2 = factory2.createMask();
mask2.showMask();
IProtectiveSuit protectiveSuit2 = factory2.createProtective();
protectiveSuit2.showSuit();
}
}
```
## 几种工厂模式的特点
简单工厂模式:
- 简单工厂模式有唯一的工厂类,工厂类的创建方法根据传入的参数做if-else条件判断,决定最终创建什么样的产品对象。
工厂方法模式:
- 工厂方法模式由多个工厂类实现工厂接口,利用多态来创建不同的产品对象,从而避免了冗长的if-else条件判断。
抽象工厂模式:
- 抽象工厂模式把产品子类进行分组,同组中的不同产品由同一个工厂子类的不同方法负责创建,从而减少了工厂子类的数量。
# 总结
抽象工厂模式要解决的是在一个产品族存在多个不同类型的产品的情况下选择接口的问题。而这种场景在业务开发中也非常多见,只不过可能有时候没有将它们抽象出来。
如果知道在什么场景下可以通过抽象工程优化代码,那么在代码层级结构以及满足业务需求方面,可以得到很好的完成功能实现并提升扩展性和优雅度。设计模式的使用满足了单一职责、开闭原则和解耦等要求。
如果说有什么缺点,那就是随着业务的场景功能不断拓展,可能会加大类实现上的复杂度。但随着其他设计方式的引入,以及代理类和自动生成加载的方式,这种设计上的欠缺也可以解决。

【设计模式】抽象工厂模式