从下面一个例子看一下几个模式之间的区别,代码很简单,道理很明显;
有一个程序员 小A 工作了几年赚了一些钱,厌倦了大都市的紧张节凑,想回家开一个水厂,过一下舒适的日子。可是开工厂也需要一定的管理方法,小A 同志毕竟是程序员啊,设计模式啥的还是懂一点的,所以就用设计模式来管理厂子。考虑到产品比较单一,只有dawawa和xiaohaha两种类型的矿泉水,那么只需要开一个水厂一个产品线就可以,每次缺货时告诉产品线要生产哪个产品就可以了;
/*抽象产品*/
abstract class WaterBrand {
abstract function make();
}
/*具体产品*/
class DaWaWa extends WaterBrand {
public function make() {
return " da wa wa";
}
}
class XiaoHaHa extends WaterBrand {
public function make() {
return " XiaoHaHa";
}
}
/*具体工厂类*/
class WaterFactory {
public function makeWater($brand) {
switch ($brand) {
case 'dawawa' :
return new DaWaWa();
case 'xiaohaha':
return new XiaoHaHa();
default:
return new DaWaWa();
}
}
}
$FactoryObj = new WaterFactory();
$WaterBrandObj = $FactoryObj->makeWater('DaWaWa');
$WaterBrandObj->make();
自从开了水厂, 小A 的生意非常红火,他感觉现在的生产模式有点落后,因为如果要扩大生产,每次都要告诉生产线要生产哪个牌子岂不是每次都要升级产品线,对原来的产品线影响很大,小A 心想 是时候 把当前的管理模式提升一下,把水厂分为两个:dawawa 水厂和 xiaohaha水厂,dawawa 水厂专门生产dawawa品牌,xiaohaha水厂专门生产xiaohaha专门生产xiaohaha品牌,即使要扩大生产几个品牌只需要增加水厂就可以了,对原来的水产产品线没有任何影响;
/*抽象产品*/
abstract class WaterBrand {
abstract function make();
}
/*具体产品*/
class DaWaWa extends WaterBrand {
public function make() {
return " da wa wa";
}
}
class XiaoHaHa extends WaterBrand {
public function make() {
return " XiaoHaHa";
}
}
abstract WaterFactory {
abstract function makeWater();
}
class DaWaWaWaterFactory extends WaterFactory {
public function makeWater() {
return new DaWaWa();
}
}
class XiaoHaHaWaterFactory extends WaterFactory {
public function makeWater() {
return new XiaoHaHa();
}
}
$FactoryObj = new XiaoHaHaWaterFactory();
$WaterBrandObj = $FactoryObj->makeWater();
$WaterBrandObj->make();
自从提升了管理模式之后生意还算稳定,但是他身边的朋友告诉他你的产品太单一,都是统一大小的,你可以划分一下外观大小啥的可以进一步提高销量,小A 心想对啊 按照星巴克不要脸思维 可以将矿泉水分为中瓶、大瓶、特大瓶,肯定能提高销量;小A 总结了一下目前的所有产品,如下所示:
在产品层次上,主要有dawawa 和 xiaohaha 两个品牌;
在产品族方面,所有品牌被划分为三个产品族即 中瓶产品族、 大瓶产品族、特大瓶产品族;
重新划分产品线,每条产品线能生产出同一大小(同一个产品族)的产品;
abstract class DaWaWa {
abstract function make();
}
class MidDaWaWa {
public function make() {
return "middle da wa wa";
}
}
class BigDaWaWa {
public function make() {
return "big da wa wa";
}
}
class ExtraLargeDaWaWa {
public function make() {
return "extra large da wa wa";
}
}
abstract class XiaoHaHa{
abstract function make();
}
class MidXiaoHaHa {
public function make() {
return "middle xiao ha ha";
}
}
class BigXiaoHaHa {
public function make() {
return "big xiao ha ha";
}
}
class ExtraLargeXiaoHaHa {
public function make() {
return "extra large xiao ha ha";
}
}
abstract WaterFactory {
abstract function makeDaWaWa();
abstract function makeXiaoHaHa();
}
class MidWaterFactory extends WaterFactory {
public function makeDaWaWa() {
return new MidDaWaWa();
}
public function makeXiaoHaHa() {
return new MidXiaoHaHa();
}
}
class BigWaterFactory extends WaterFactory {
public function makeDaWaWa() {
return new BigDaWaWa();
}
public function makeXiaoHaHa() {
return new BigXiaoHaHa();
}
}
class ExtraLargeWaterFactory extends WaterFactory {
public function makeDaWaWa() {
return new ExtraLargeDaWaWa();
}
public function makeXiaoHaHa() {
return new ExtraLargeXiaoHaHa();
}
}
$FactoryObj = new ExtraLargeWaterFactory ();
$WaterBrandObj = $FactoryObj->makeDaWaWa();
$WaterBrandObj->make();
通过以上的调整,水厂的生意算是稳定了下来,小A 暂时可以休息一下,享受一下生活了。
说完了水厂的事情,咱们来总结一下几种模式的特点:
首先是第一种模式:
水厂 (工厂类角色): 含有一条生产线,生成什么产品,通过条件进行判断;
抽出的产品特点 (抽象产品角色) :描述了产品的一些公共特点 (是具体产品继承的父类或者实现的接口)
具体品牌的水产品模型 (具体产品角色): 根据产品特点创造出来的模型(类),水厂根据模型生产出具体产品;
原理如下所示:
类图如下所示:
第二种模式特点,主要包含的元素:
抽出的水厂特点(抽象工厂角色): 描述了水厂的特点,按照抽出的特点进行建厂(是具体工厂角色必须实现的接口或者必须继承的父类)
水厂 (工厂类角色): 含有一条生产线,生成什么产品,通过条件进行判断;
抽出的产品特点 (抽象产品角色) :描述了产品的一些公共特点 (是具体产品继承的父类或者实现的接口)
具体品牌的水产品模型 (具体产品角色): 根据产品特点创造出来的模型(类),水厂根据模型生产出具体产品;
工厂方法模式原理图如下所示:
工厂方法模式类图如下所示:
第三种模式在角色上并没有增加,但是引入了产品族的概念,就是说不通产品之间有相同特点的就是一个产品族,比如 大瓶的dawawa和 大瓶的xiaohaha 就是一个产品族,特大瓶的dawawa和特大瓶的xiaohaha也是一个产品族;
抽象工厂模式原理图:
抽象工厂模式类图如下所示: