PHP设计模式之工厂模式定义与用法详解


Posted in PHP onApril 03, 2018

本文实例讲述了PHP设计模式之工厂模式定义与用法。分享给大家供大家参考,具体如下:

工厂模式(Factory Design Pattern)作为一种创建型设计模式, 遵循了开放-封闭原则, 对修改封闭, 对扩展开放. 工厂方法(Factory Method)模式就是要创建"某种东西". 对于工厂方法模式, 要创建的"东西"是一个产品,这个产品与创建它的类之间不存在绑定.实际上,为了保持这种松耦合,客户会通过一个工厂发出请求. 再由工厂创建所请求的产品.也可以换种方式考虑, 利用工厂方法模式, 请求者只发出请求, 而不具体创建产品.

工厂的工作

先建立一个工厂的接口

Factory.php

<?php
abstract class Factory
{
 //抽象的创建对象的方法
 protected abstract function createProduct();
 //该方法调用createProduct方法返回一个产品对象.
 public function start()
 {
   return $this->createProduct();
 }
}

start方法返回一个产品,该方法调用createProduct方法完成产生产品的操作.所以createProduct的具体实现要构建并返回一个按Product接口实现的产品对象.

比如产品都有一个共同的方法getProperties(), 以下是对应Product接口

Product.php

<?php
//产品接口
interface Product
{
 public function getProperties();
}

接着, 我们要建立两个工厂,文本工厂TextFactory和图像工厂phptoFactory

TextFactory.php

<?php
include_once('Factory.php');
include_once('TextProduct.php');
class TextFactory extends Factory
{
 protected function createProduct()
 {
  $product = new TextProduct();
  return $product->getProperties();
 }
}

PhotoFactory.php

<?php
include_once('Factory.php');
include_once('PhotoProduct.php');
class PhotoFactory extends Factory
{
 protected function createProduct()
 {
  $product = new PhotoProduct();
  return $product->getProperties();
 }
}

可以看到,在工厂方法的实现中, getProperties方法引入了多态(polymorphism), 将用这个方法返回"文本"或"图像". 同一个getProperties()有多个(poly)不同的形态(morphs), 这就是多态.在这种情况下, 其中一种形式返回文本, 而另一种返回图像.

可以在properties这个实现中放入你想要的任何东西,工厂方法设计将会创建这个对象, 并把他返回给Client使用.

下面的是两个产品的实现

TextProduct.php

<?php
include_once('Product.php');
class TextProduct implements Product
{
 public function getProperties()
 {
  return "这里是文本产品";
 }
}

PhotoProduct.php

<?php
include_once('Product.php');
class PhotoProduct implements Product
{
 //这是产品具有的方法
 public function getProperties()
 {
  return "这里是图像产品";
 }
}

这两个产品实现了Product接口中的抽象方法getProperties(),

客户(Client)

我们并不希望客户直接做出产品请求.实际上, 我们希望客户通过Factory工厂接口做出请求.这样一来,如果以后我们增加了产品或者工厂, 客户可以做同样的请求来得到更多类型的产品 , 而不会破坏这个应用:

Client.php

<?php
include_once('PhotoFactory.php');
include_once('TextFactory.php');
class Client
{
 public function __construct()
 {
  $this->somePhotoObject = new PhotoFactory();
  echo $this->somePhotoObject->start() . '<br />';
  $this->someTextObject = new TextFactory();
  echo $this->someTextObject->start() . '<br />';
 }
}
$worker = new Client();

运行Client.php, 得到下面的结果

这里是图像产品
这里是文本产品

注意: Client对象并没有向产品直接做出请求, 而是通过工厂来请求. 重要的是, 客户并不实现产品特性, 而留给产品实现来体现.

调整产品

设计模式的真正价值并不是提高操作的速度, 而是加快开发的速度.

如果现在需求变化了, 需要对图像产品做出修改, 只需要修改相应的产品PhotoProduct的getProperties方法即可

对象的改变看起来很简单 不过Product的getProperties()方法仍保持相同的接口,请求工厂返回一个属性对象

增加新产品和参数化请求

问题来了,如果要增加更多的图像和文本说明, 有没有必要每次增加一个新的区域就增加一个新的具体的工厂类?这意味着要为每个新区域增加一个新工厂和产品.于是,我们引进了参数化工厂设计模式

参数化工厂设计模式和一般的工厂设计模式的主要区别之一是客户包含工厂和产品的引用. 在参数化请求中, Client类必须指定产品, 而不是产品工厂. createProduct()操作中的参数是由客户传入一个产品; 所以客户必须指出它想要的具体产品. 不过, 这个请求仍然是通过工厂接口Factory发出的. 所以, 尽管客户包含一个产品引用, 但通过Factory, 客户仍然与产品分离.

一个工厂多个产品(参数化工厂方法)

对于大多数请求, 参数化工厂方法更为简单, 因为客户只需要处理一个具体工厂.工厂方法操作有一个参数,指示需要创建的产品.而在原来的设计中, 每个产品都有自己的工厂, 不需要另个传递参数; 产品实现依赖于各个产品特定的工厂.

新工厂接口

Factory.php

<?php
abstract class Factory
{
 //抽象的创建对象的方法
 protected abstract function createProduct(Product $product);
 //该方法由factoryMethod方法返回一个产品对象.
 public function start($product)
 {
   return $this->createProduct($product);
 }
}

在这个新的Factory接口中可以看到, create()start()都需要一个参数,指定一个Product对象, 而不是Product接口的一个特定实现, 所以可以接受任何Product的具体实例.

工厂具体实现

具体的创建者类CommonFactory实现了createProduct(),如下

CommonFactory.php

<?php
include_once('Factory.php');
include_once('Product.php');
class CommonFactory extends Factory
{
 protected function createProduct(Product $product)
 {
  return $product->getProperties();
 }
}

这个类调用Product的方法getProperties将产品返回给客户.

新产品

具体产品的变化并不会改变原来的Product接口,还是原来的代码

<?php
//产品接口
interface Product
{
 public function getProperties();
}

例如, 现在有一个钢笔产品PenProduct

PenProduct.php

<?php
include_once('Product.php');
class PenProduct implements Product
{
 public function getProperties()
 {
  return "钢笔产品";
 }
}

客户Clent(有参数)

<?php
include_once('CommonFactory.php');
include_once('PenProduct.php');
class Client
{
 public function __construct()
 {
  $commonFactory = new CommonFactory();
  echo $commonFactory->start(new PenProduct());
 }
}
$worker = new Client();

运行后输出

钢笔产品

以后如果开发出了新的产品, 只需要创建对应的产品类, 然后客户指定想要的新产品 , 即可返回客户需要的产品.

总结:

产品改变: 接口不变

使用设计模式的一大好处就是可以很容易地对类做出改变, 而不会破坏更大的程序. 之所以能够容易地做出改变, 秘诀在于保持接口不变, 而只改变内容.

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php array_map array_multisort 高效处理多维数组排序
Jun 11 PHP
PHP 冒泡排序 二分查找 顺序查找 二维数组排序算法函数的详解
Jun 25 PHP
PHP中CURL的CURLOPT_POSTFIELDS参数使用细节
Mar 17 PHP
浅析PHP微信支付通知的处理方式
May 25 PHP
php下Memcached入门实例解析
Jan 05 PHP
php调整服务器时间的方法
Apr 03 PHP
php返回相对时间(如:20分钟前,3天前)的方法
Apr 14 PHP
PHP简单实现无限级分类的方法
May 13 PHP
PHP简单创建压缩图的方法
Aug 24 PHP
php+jQuery递归调用POST循环请求示例
Oct 14 PHP
PHP实现的分解质因数操作示例
Aug 01 PHP
PHP页面静态化――纯静态与伪静态用法详解
Jun 05 PHP
PHP设计模式之原型模式定义与用法详解
Apr 03 #PHP
thinkPHP框架自动填充原理与用法分析
Apr 03 #PHP
PHP设计模式之适配器模式定义与用法详解
Apr 03 #PHP
PHP延迟静态绑定的深入讲解
Apr 02 #PHP
PHP设计模式之装饰器模式定义与用法详解
Apr 02 #PHP
PHP设计模式之状态模式定义与用法详解
Apr 02 #PHP
PHP设计模式之模板方法模式定义与用法详解
Apr 02 #PHP
You might like
yii操作cookie实例简介
2014/07/09 PHP
Symfony数据校验方法实例分析
2015/01/26 PHP
PHP中的switch语句的用法实例详解
2015/10/21 PHP
php简单备份与还原MySql的方法
2016/05/09 PHP
jQuery 常见操作实现方式和常用函数方法总结
2011/05/06 Javascript
JS上传前预览图片实例
2013/03/25 Javascript
jQuery实现弹出带遮罩层的居中浮动窗口效果
2016/09/12 Javascript
javascript 解决浏览器不支持的问题
2016/09/24 Javascript
Bootstrap3 多个模态对话框无法显示的解决方案
2017/02/23 Javascript
js 数字、字符串、布尔值的转换方法(必看)
2017/04/07 Javascript
Javascript实现一个简单的输入关键字添加标签效果实例
2017/06/01 Javascript
vue router demo详解
2017/10/13 Javascript
jquery radio 动态控制选中失效问题的解决方法
2018/02/28 jQuery
基于JS正则表达式实现模板数据动态渲染(实现思路详解)
2020/03/07 Javascript
在Python的Django框架中创建语言文件
2015/07/27 Python
Python语言检测模块langid和langdetect的使用实例
2019/02/19 Python
Python3 串口接收与发送16进制数据包的实例
2019/06/12 Python
Python如何优雅获取本机IP方法
2019/11/10 Python
python实现全排列代码(回溯、深度优先搜索)
2020/02/26 Python
python数据预处理 :样本分布不均的解决(过采样和欠采样)
2020/02/29 Python
利用Python制作动态排名图的实现代码
2020/04/09 Python
Python3+PyCharm+Django+Django REST framework配置与简单开发教程
2021/02/16 Python
东芝官网商城:还原日式美学,打造美好生活
2018/12/27 全球购物
专业毕业生个性的自我评价
2013/10/03 职场文书
个人简历自我评价八例
2013/10/31 职场文书
大学生实习思想汇报
2014/01/12 职场文书
关于保护环境的标语
2014/06/09 职场文书
镇班子对照检查材料思想汇报
2014/09/24 职场文书
党的群众路线教育实践活动专题组织生活会发言材料
2014/10/17 职场文书
骨干教师事迹材料
2014/12/17 职场文书
2015年求职自荐信范文
2015/03/04 职场文书
《生物入侵者》教学反思
2016/02/16 职场文书
《打电话》教学反思
2016/02/22 职场文书
创业计划之特色精品店
2019/08/12 职场文书
Python 发送SMTP邮件的简单教程
2021/06/24 Python
java协程框架quasar和kotlin中的协程对比分析
2022/02/24 Java/Android