创建型设计模式:抽象工厂(Abstract Factory)
我们在使用简单工厂或工厂方法,createProduct()是直接返回了已完成的产品。而有些产品由好几个零部件组装而成,各个零部件单独生产,并相关联。这次我们要介绍的是生产自行车的工厂。
自行车工厂
自行车工厂的任务是:
- 生产两个品牌系列:凤牌和凰牌的自行车
- 生产自行车的各个系列相关零部件:车架(BikeRack),车轮(Wheel)和脚踏板(Pedal),最后组装自行车。
品牌差异
因为凤牌和凰牌自行车的定位不同,它们各自的车架,车轮和脚踏板的材料以及制作工艺是比较大的差异,所以不能统一在一个工厂生产。
很自然,我们会想到在两个工厂:FengBikePartsFactory和HuangBikePartsFactory生产。
组装所用零部件类别相同
虽然两个品牌零部件不同,但它们所用到的零部件类别规格相同,且组装方式也一样。为了规范零部件的规格和流程,我们抽象规范生产零部件的工厂接口,BikePartsFactory:
<pre data-language-edit="Java" spellcheck="false">```java
<span class="hljs">//规范零部件车架</span>
<span class="hljs">public</span> <span class="hljs">abstract</span> <span class="hljs">class</span> <span class="hljs">BikeRack</span> {
}
<span class="hljs">//规范零部件脚踏</span>
<span class="hljs">public</span> <span class="hljs">abstract</span> <span class="hljs">class</span> <span class="hljs">Pedal</span> {
}
<span class="hljs">//规范零部件车轮</span>
<span class="hljs">public</span> <span class="hljs">abstract</span> <span class="hljs">class</span> <span class="hljs">Wheel</span> {
}
<span class="hljs">public</span> <span class="hljs">abstract</span> <span class="hljs">class</span> <span class="hljs">BikePartsFactory</span> {
<span class="hljs">abstract</span> BikeRack <span class="hljs">createRack()</span>;
<span class="hljs">abstract</span> Wheel <span class="hljs">createWheel()</span>;
<span class="hljs">abstract</span> Pedal <span class="hljs">createPedal()</span>;
}
各自工厂就可以继承BikePartsFacotry,生产各自的零部件。
### 凤自行车零部件工厂
凤自行车的零部件实现零部件的接口,最后由FengBikePartsFactory生产。
<pre data-language-edit="Java" spellcheck="false">```java <span class="hljs">//实现BikeRack要求,满足自行车架规格</span> <span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">FengBikeRack</span> <span class="hljs">extends</span> <span class="hljs">BikeRack</span>{} <span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">FengWheel</span> <span class="hljs">extends</span> <span class="hljs">Wheel</span> {} <span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">FengPedal</span> <span class="hljs">extends</span> <span class="hljs">Pedal</span>{}
<span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">FengBikePartsFactory</span> <span class="hljs">extends</span> <span class="hljs">BikePartsFactory</span>{ <span class="hljs">@Override</span> BikeRack <span class="hljs">createRack()</span> { <span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">FengBikeRack</span>(); } <span class="hljs">@Override</span> Wheel <span class="hljs">createWheel()</span> { <span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">FengWheel</span>(); } <span class="hljs">@Override</span> Pedal <span class="hljs">createPedal()</span> { <span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">FengPedal</span>(); } }
凰自行车零部件工厂
同样,凰自行车零部件实现零部件的接口,最后由HuangBikePartsFactory生产。
<pre data-language-edit="Java" spellcheck="false">```java
<span class="hljs">//实现BikeRack要求,满足自行车架规格</span>
<span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">HuangBikeRack</span> <span class="hljs">extends</span> <span class="hljs">BikeRack</span>{}
<span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">HuangWheel</span> <span class="hljs">extends</span> <span class="hljs">Wheel</span> {}
<span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">HuangPedal</span> <span class="hljs">extends</span> <span class="hljs">Pedal</span>{}
<span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">HuangBikePartsFactory</span> <span class="hljs">extends</span> <span class="hljs">BikePartsFactory</span>{
<span class="hljs">@Override</span>
BikeRack <span class="hljs">createRack()</span> {
<span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">HuangBikeRack</span>();
}
<span class="hljs">@Override</span>
Wheel <span class="hljs">createWheel()</span> {
<span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">HuangWheel</span>();
}
<span class="hljs">@Override</span>
Pedal <span class="hljs">createPedal()</span> {
<span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">HuangPedal</span>();
}
}
### 自行车组装
简化实现中的自行车组装,组装车间只需要拿到每个品牌各自的一套零部件,就可以按标准流程组装完成。
<pre data-language-edit="Java" spellcheck="false">```java <span class="hljs">public</span> <span class="hljs">class</span> <span class="hljs">BikeAssemble</span> { <span class="hljs">private</span> BikePartsFactory bikePartsFactory;
<span class="hljs">public</span> <span class="hljs">BikeAssemble(BikePartsFactory bikePartsFactory)</span> {
<span class="hljs">this</span>.bikePartsFactory = bikePartsFactory;
}
<span class="hljs">public</span> Bike <span class="hljs">create()</span> {
<span class="hljs">BikeRack</span> <span class="hljs">bikeRack</span> <span class="hljs">=</span> bikePartsFactory.createRack();
<span class="hljs">Wheel</span> <span class="hljs">wheel</span> <span class="hljs">=</span> bikePartsFactory.createWheel();
<span class="hljs">Pedal</span> <span class="hljs">pedal</span> <span class="hljs">=</span> bikePartsFactory.createPedal();
<span class="hljs">return</span> <span class="hljs">new</span> <span class="hljs">Bike</span>(bikeRack,wheel, pedal);
}
}
那么要生产凤自行车和凰自行车,只要告诉那个零部件工厂生产即可。
生产方式:
<pre data-language-edit="Java" spellcheck="false">```java
<span class="hljs">public</span> <span class="hljs">static</span> <span class="hljs">void</span> <span class="hljs">main(String[] args)</span> {
<span class="hljs">//生产凤自行车</span>
<span class="hljs">BikeAssemble</span> <span class="hljs">assemble</span> <span class="hljs">=</span> <span class="hljs">new</span> <span class="hljs">BikeAssemble</span>(<span class="hljs">new</span> <span class="hljs">FengBikePartsFacotry</span>());
<span class="hljs">Bike</span> <span class="hljs">fengBike</span> <span class="hljs">=</span> assemble.create();
<span class="hljs">//生产凰自行车</span>
<span class="hljs">BikeAssemble</span> <span class="hljs">assemble</span> <span class="hljs">=</span> <span class="hljs">new</span> <span class="hljs">BikeAssemble</span>(<span class="hljs">new</span> <span class="hljs">HuangBikePartsFacotry</span>());
<span class="hljs">Bike</span> <span class="hljs">huangBike</span> <span class="hljs">=</span> assemble.create();
}
抽象工厂
----
上述生产自行车的工厂使用就是我们要介绍的设计模式:**抽象工厂**。
> **抽象工厂模式:**提供一个接口,用于创建相关或者依赖对象的系列,而不需要明确指定具体类。
抽象工厂是创建型设计模式,类图如下:
<figure class="image">![](https://uimg.majing.io/post/1/36/3507/1664010489521_GX6Bd.png)</figure>AbstractFactory:抽象工厂会提供接口生成相关或者相互依赖的产品家族。
ConcreteFactory:具体化工厂,它会实现抽象工厂提供的生成产品家族接口。
ProductA:相关联家族的产品抽象,由抽象定义创建产品方法。
ConcreteProduct:具体的产品,实现抽象产品接口ProductA,并在系列的具体工厂实现创建。
Client:调用工厂,组合具体工厂创建的相关产品,创建最终产品。
抽象工厂 VS 工厂方法
------------
1. 工厂方法只提供用一个方法,而抽象工厂提供产品家族的多个创建方法。
2. 工厂方法往往创建的是单一产品,而抽象工厂创建的是相关或者相互依赖的产品家族。