PHP实现设计模式中的抽象工厂模式详解


Posted in PHP onOctober 11, 2014

抽象工厂模式(Abstact Factory)是一种常见的软件设计模式。该模式为一个产品族提供了统一的创建接口。当需要这个产品族的某一系列的时候,可以为此系列的产品族创建一个 具体的工厂类。

【意图】

抽象工厂模式提供一个创建一系统相关或相互依赖对象的接口,而无需指定它们具体的类【GOF95】

【抽象工厂模式结构图】

PHP实现设计模式中的抽象工厂模式详解

【抽象工厂模式中主要角色】

抽象工厂(Abstract Factory)角色:它声明一个创建抽象产品对象的接口。通常以接口或抽象类实现,所有的具体工厂类必须实现这个接口或继承这个类。

具体工厂(Concrete Factory)角色:实现创建产品对象的操作。客户端直接调用这个角色创建产品的实例。这个角色包含有选择合适的产品对象的逻辑。通常使用具体类实现。

抽象产品(Abstract Product)角色:声明一类产品的接口。它是工厂方法模式所创建的对象的父类,或它们共同拥有的接口。

具体产品(Concrete Product)角色:实现抽象产品角色所定义的接口,定义一个将被相应的具体工厂创建的产品对象。其内部包含了应用程序的业务逻辑。

【抽象工厂模式的优缺点】

抽象工厂模式的优点:
1、分离了具体的类
2、使增加或替换产品族变得容易
3、有利于产品的一致性

抽象工厂模式的缺点: 难以支持新种类的产品。这是因为AbstractFactory接口确定了可以被创建的产品集合。支持新各类的产品就需要扩展访工厂接口,从而导致 AbstractFactory类及其所有子类的改变。
抽象工厂就是以一种倾斜的方式支持增加新的产品中,它为新产品族的增加提供了方便,而不能为新的产品等级结构的增加提供这样的方便。

【抽象工厂模式适用场景】

以下情况应当使用抽象工厂模式:
1、一个系统不应当依赖于产品类实例如何被创建、组合和表达的细节,这对于所有形态的工厂模式都是重要的。
2、这个系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
3、 同属于同一个产品族的产品是在一起使用的,这一约束必须在系统的设计中体现出来。
4、系统提供一个产品类的库,所有的产品以同样的接口出现,从而使用客户端不依赖于实现
【Java与模式189页】

Abstract Factory模式的几个要点:

1、如果没有应对“多系列对象构建”的需求变化,则没有必要使用Abstract Factory模式。
2、“系列对象”指的是这项对象之间有相互依赖、或作用的关系。
3、Abstract Factory模式主要在于应对“新系列”的需求变动。缺点是难以应对
“新对象”的需求变动。这一点应该注意,就像前面说的,如果我们现在要在加入
其他系列的类,代码的改动会很大。
4、Abstract Factory模式经常和Factory Method模式共同组合来应对
“对象创建”的需求变化。

抽象工厂中的增加

1. 在产品等级结构的数目不变的情况下,增加新的产品族,就意味着在每一个产品等级结构中增加一个(或者多个)新的具体 (或者抽象和具体)产品角色。 由于工厂等级结构是与产品等级结构平行的登记机构,因此,当产品等级结构有所调整时, 需要将工厂等级结构做相应的调整。现在产品等级结构中出现了新的元素,因此, 需要向工厂等级结构中加入相应的新元素就可以了。 换言之,设计师只需要向系统中加入新的具体工厂类就可以了,没有必要修改已 有的工厂角色或者产品角色。因此,在系统中的产品族增加时,抽象工厂模式是支持“开-闭”原则的。

2. 在产品族的数目不变的情况下,增加新的产品等级结构。换言之,所有的产品等级结构 中的产品数目不会改变,但是现在多出一个与现有的产品等级结构平行的新的产品等级结构。 要做到这一点,就需要修改所有的工厂角色,给每一个工厂类都增加一个新的工厂方法, 而这显然是违背“开?闭”原则的。换言之,对于产品等级结构的增加,抽象工厂模式是不支持“开?闭”原则的。

综合起来,我们可以知道,在已有的抽象产品中添加其具体产品,支持“开—闭原则”, 然而在添加其抽象产品时,确不支持“开—闭”原则。抽象工厂模式以一种倾斜的 方式支持增加新的产品,它为新产品族的增加提供方便,而不能为新的产品等级 结构的增加提供这样的方便。

【抽象工厂模式与其它模式】

单例模式(singleton模式):具体工厂类可以设计成单例类,由于工厂通常有一个就可以,因此具体工厂子类一般都实现为一个Singleton。

工厂方法模式(factory method模式):抽象工厂创建产品的方法定义为工厂方法。

原型模式(prototype模式):如果有多个可能的产品系列,具体的工厂也可以使用原型模式,具体工厂使用产品系列中。

每一个产品的原型进行实例化并且通过复制它的原型来创建新的产品。

【抽象工厂模式PHP示例】

<?php

/**

 * 抽象工厂模式 2010-05-28 sz

 * @author phppan.p#gmail.com  

 * @package design pattern

 */

 

/**

 * 抽象工厂

 */

interface AbstractFactory {

    /**

     * 创建等级结构为A的产品的工厂方法

     */

    public function createProductA();

 

     /**

     * 创建等级结构为B的产品的工厂方法

     */

    public function createProductB();

 

}

 

/**

 * 具体工厂1

 */

class ConcreteFactory1 implements AbstractFactory{

 

    public function createProductA() {

        return new ProductA1();

    }

 

    public function createProductB() {

        return new ProductB1();

    }

}

 

 

/**

 * 具体工厂2

 */

class ConcreteFactory2 implements AbstractFactory{

 

    public function createProductA() {

        return new ProductA2();

    }

 

    public function createProductB() {

        return new ProductB2();

    }

}

 

/**

 * 抽象产品A

 */

interface AbstractProductA {

 

    /**

     * 取得产品名

     */

    public function getName();

}

 

/**

 * 抽象产品B

 */

interface AbstractProductB {

 

    /**

     * 取得产品名

     */

    public function getName();

}

 

/**

 * 具体产品A1

 */

class ProductA1 implements AbstractProductA {

    private $_name;

 

    public function __construct() {

        $this->_name = 'product A1';

    }

 

    public function getName() {

        return $this->_name;

    }

}

 

 

/**

 * 具体产品A2

 */

class ProductA2 implements AbstractProductA {

    private $_name;

 

    public function __construct() {

        $this->_name = 'product A2';

    }

 

    public function getName() {

        return $this->_name;

    }

}

 

 

/**

 * 具体产品B1

 */

class ProductB1 implements AbstractProductB {

    private $_name;

 

    public function __construct() {

        $this->_name = 'product B1';

    }

 

    public function getName() {

        return $this->_name;

    }

}

 

/**

 * 具体产品B2

 */

class ProductB2 implements AbstractProductB {

    private $_name;

 

    public function __construct() {

        $this->_name = 'product B2';

    }

 

    public function getName() {

        return $this->_name;

    }

}

 

 

/**

 * 客户端

 */

class Client {

 

     /**

     * Main program.

     */

    public static function main() {

        self::run(new ConcreteFactory1());

        self::run(new ConcreteFactory2());

    }

 

    /**

     * 调用工厂实例生成产品,输出产品名

     * @param   $factory    AbstractFactory     工厂实例

     */

    public static function run(AbstractFactory $factory) {

        $productA = $factory->createProductA();

        $productB = $factory->createProductB();

        echo $productA->getName(), '<br />';

        echo $productB->getName(), '<br />';

    }

 

}

 

Client::main();

?>
PHP 相关文章推荐
php adodb分页实现代码
Mar 19 PHP
php的chr和ord函数实现字符加减乘除运算实现代码
Dec 05 PHP
一个PHP的远程图片抓取函数分享
Sep 25 PHP
使用PHP导出Word文档的原理和实例
Oct 21 PHP
使用PHP强制下载PDF文件示例
Jan 17 PHP
php数组去重复数据示例
Feb 25 PHP
php判断数组元素中是否存在某个字符串的方法
Jun 14 PHP
php连接mysql数据库
Mar 21 PHP
[原创]PHP正则删除html代码中a标签并保留标签内容的方法
May 23 PHP
微信小程序发送订阅消息的方法(php 为例)
Oct 30 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
Mar 30 PHP
PHP重载基础知识回顾
Sep 10 PHP
php中字符集转换iconv函数使用总结
Oct 11 #PHP
PHP生成网站桌面快捷方式代码分享
Oct 11 #PHP
PHP中执行cmd命令的方法
Oct 11 #PHP
PHP @ at 记号的作用示例介绍
Oct 10 #PHP
php json_encode()函数返回json数据实例代码
Oct 10 #PHP
PHP中构造函数和析构函数解析
Oct 10 #PHP
Javascript与PHP验证用户输入URL地址是否正确
Oct 09 #PHP
You might like
php设计模式 Delegation(委托模式)
2011/06/26 PHP
PHP几个数学计算的内部函数学习整理
2011/08/06 PHP
浅析PHP页面局部刷新功能的实现小结
2013/06/21 PHP
如何让CI框架支持service层
2014/10/29 PHP
jQuery链式操作如何实现以及为什么要用链式操作
2013/01/17 Javascript
当鼠标滑过文本框自动选中输入框内容的JS代码分享
2013/11/26 Javascript
node.js中使用socket.io的方法
2014/12/15 Javascript
JavaScript判断是否为数组的3种方法及效率比较
2015/04/01 Javascript
JavaScript位置与大小(1)之正确理解和运用与尺寸大小相关的DOM属性
2015/12/26 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
Angular.js实现多个checkbox只能选择一个的方法示例
2017/02/24 Javascript
详解angularJs指令的3种绑定策略
2017/04/13 Javascript
vue 怎么创建组件及组件使用方法
2017/07/27 Javascript
vue v-model实现自定义样式多选与单选功能
2018/07/05 Javascript
H5+C3+JS实现五子棋游戏(AI篇)
2020/05/28 Javascript
vue等两个接口都返回结果再执行下一步的实例
2020/09/08 Javascript
[36:33]Ti4 循环赛第四日 附加赛NEWBEE vs Mouz
2014/07/13 DOTA
Python实现的生成格雷码功能示例
2018/01/24 Python
python 用正则表达式筛选文本信息的实例
2018/06/05 Python
让Python脚本暂停执行的几种方法(小结)
2019/07/11 Python
python实现人工智能Ai抠图功能
2019/09/05 Python
python修改FTP服务器上的文件名
2019/09/11 Python
keras读取训练好的模型参数并把参数赋值给其它模型详解
2020/06/15 Python
python闭包与引用以及需要注意的陷阱
2020/09/18 Python
html5 Canvas画图教程(5)—canvas里画曲线之arc方法
2013/01/09 HTML / CSS
健康监测猫砂:Pretty Litter
2017/05/25 全球购物
阿迪达斯墨西哥官方网站:adidas墨西哥
2017/11/03 全球购物
英国奢侈品牌时尚购物平台:Farfetch(支持中文)
2020/02/18 全球购物
俄罗斯建筑和装饰材料在线商店:Stroilandia
2020/07/25 全球购物
俄罗斯厨房产品购物网站:COOK HOUSE
2021/03/15 全球购物
《狐假虎威》教学反思
2014/02/07 职场文书
学校领导班子群众路线整改措施
2014/09/16 职场文书
公司领导九九重阳节发言稿2014
2014/09/25 职场文书
证券区域经理岗位职责
2015/04/10 职场文书
立春观后感
2015/06/18 职场文书
新闻发布会新闻稿
2015/07/17 职场文书