官方定义
提供一个用于创建相关或相关对象族的接口,而无须指定其具体类。
理解
抽象工厂针对的是多个产品族结构,一个产品族内有多个产品
抽象工厂的角色
- 抽象工厂
- 抽象产品(通用的一类对象接口)
- 具体工厂
- 具体产品(继承通用对象或接口后扩展特有属性)
现实中的例子
比如说:抽象工厂生产的抽象产品是刀,枪,棍一类的武器,那具体工厂就可能在生产具体的武器:每个具体的工厂生产的具体的武器 可能在外观 威力,制作工艺上可能不一样。但是武器这个特性是不会发生太大改变的。
其中最为关键的角色不是抽象工厂本身,而是抽象的产品。抽象产品的好坏才是直接决定了抽象工厂和具体工厂能否发挥最大作用的关键所在。 所以找到正确的抽象很重要
UML类图
程序的例子
// 武器工厂 (抽象工厂)
interface WeaponsFactory
{
public function makingBullets(); // 子弹
public function makingClip(); // 弹夹
public function makingSight(); // 瞄准镜
}
// 中国工厂
class ChinaFactory implements WeaponsFactory
{
public function makingBullets()
{
return new ChinaBullets();
}
public function makingClip()
{
return new ChinaClip();
}
public function makingSight()
{
return new ChinaSight();
}
}
// 美国工厂
class USAFactory implements WeaponsFactory
{
public function makingBullets()
{
return new USABullets();
}
public function makingClip()
{
return new USAClip();
}
public function makingSight()
{
return new USASight();
}
}
// 客户端调用
class client
{
public function make(WeaponsFactory $weaponsFactory)
{
$bullets = $weaponsFactory->makingBullets();
$clip = $weaponsFactory->makingClip();
$sight = $weaponsFactory->makingSight();
}
}
为什么要使用抽象工厂模式?
- 对于不同产品系列有比较多共性特征时,可以使用抽象工厂模式,有助于提升组件的复用性。
- 当需要提升代码的扩展性并降低维护成本时,把对象的创建和使用过程分开,能有效地将代码统一到一个级别上。
- 解决跨平台带来的兼容性问题。
优点
- 符合开闭原则。当我们需要添加新的工厂类时,只用新继承一个类,不用修改抽象工厂和其他具体类。
- 可以保证同一工厂生成的产品符合预期。通过抽象工厂定义了同一的抽象产品功能,只要是继承了这个抽象工厂,本质的抽象产品功能是不会发生改变的。
- 满足单一原则。
- 容易增加新的产品系列。
缺点
- 增加代码量
- 增加学习成本
- 变更产品的结构困难。
判断要不要创建对象的参考标准
- 封装变化:创建逻辑有可能变化,封装城工厂类之后,创建逻辑的变更对调用者透明。
- 代码复用:创建代码抽离到独立的工厂类之后可以复用
- 隔离复杂性:封装了创建的复杂性,调用者不用关心如何创建对象。
- 控制复杂度:将创建代码抽离出来,让原本的函数或类职责更单一,代码更简洁。
总结
抽象工厂模式的使用和创建都很简单,不过这并不是应用这个模式的重点,重点其实在于能否能明白抽象工厂的本质,也就是如何寻找到正确的抽象。只有找到了正确的抽象产品,才能发挥抽象工厂模式的作用
希望各位能提出自己宝贵的建议,与诸君共同成长。!!十分感谢!