概述
抽象工厂模式对同一类产品实现了封装,上层应用(客户端)只需调用相应的工厂接口来创建具体的产品,无需关心产品是如何创建。
特点
对接口的规范化提供很好的一致性和扩展性。
工厂角色
要理解抽象工厂设计模式,需要先了解以下概念。(在之后的代码中会体现)
抽象工厂:负责定义工厂接口,所有继承于此工厂的子类(也叫具体工厂)必须实现抽象工厂内定义的接口(或方法)。抽象工厂在php中,可以使用interface或者abstract来定义。interface和abstract都是php内的抽象接口的定义方式,但是两个函数有不同的应用场景,具体可以参考PHP中的 抽象类(abstract class)和 接口(interface)
具体工厂:负责实现抽象工厂的具体接口,不同的具体工厂均继承与抽象工厂。由于抽象工厂定义了统一的接口规范,所以可以根据需求实现不同的工厂,从而做出不同的产品供上层应用调用。
抽象产品:定义某类产品的接口,所有的具体产品需要继承此类,并实现该类提供的接口。(使用inteface或abstract定义)
具体产品:实现抽象产品。
以上的4个角色构成了一个完整的抽象工厂设计模式
举个栗子:
1、水果工厂这类的工厂(抽象工厂),它应该是生产水果的工厂,所以它有个生产水果方法createFruit(),这个就是抽象工厂给我们的概念(编程中理解为接口)。
2、水果工厂又分有很多种,比如生产苹果的工厂、生产香蕉的工厂等等,这些工厂就是具体工厂。当然了,这些工厂肯定是水果工厂,而且肯定是生产水果的(不然都不好意思叫水果工厂),所以这些工厂都要实现水果工厂(抽象工厂)的生产水果方法createFruit()。
3、既然已经有水果生产出来了,那么这些水果都有相同的属性,比如名字、重量、颜色、口感等,这就是我们的抽象产品,定义某类产品的接口。
4、具体的产品(例如苹果、香蕉)则是抽象工厂的最终产物。
具体实现代码
/******抽象工厂******/
/**
* 水果类工厂
*/
abstract class FruitFactory
{
abstract public function createFruit();//生产水果方法
}
/******具体工厂******/
//苹果工厂
class AppleFactory extends FruitFactory
{
public function createFruit()
{
return new Apple();
}
}
//香蕉工厂
class BananaFactory extends FruitFactory
{
public function createFruit()
{
return new Banana();
}
}
/******抽象产品******/
/*水果类产品*/
abstract class Fruit
{
abstract public function name();//水果名
}
/******具体产品******/
/*苹果*/
class Apple extends Fruit
{
public function name()
{
echo 'i am apple';
}
}
/*香蕉*/
class Banana extends Apple
{
public function name()
{
echo 'i am banana';
}
}
/******测试代码******/
//1、我们来到苹果工厂
$appleFactory = new AppleFactory();
//2、告诉工厂,帮我们造一个苹果
$apple = $appleFactory->createFruit();
//3、我们得到了一个苹果,可以使用它
$apple->name();//输出i am apple
//下面再去香蕉厂
$bananaFactory = new BananaFactory();
$banana = $bananaFactory->createFruit();
$banana->name();//输出 i am banana
抽象工厂模式优点
- 解耦, 分离了客户端和类,客户端只需要去找相应的工厂,则可以得到所需的产品
- 易于扩展,当水果厂添加某项功能,或者要为水果这类产品添加某项属性时,只需要在抽象工厂和抽象产品类中添加相应接口,其继承者去实现即可。
- 规范化,可保持接口的一致性。