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 相关文章推荐
全文搜索和替换
Oct 09 PHP
php遍历所有文件及文件夹的方法深入解析
Jun 08 PHP
关于ob_get_contents(),ob_end_clean(),ob_start(),的具体用法详解
Jun 24 PHP
PHP分页效率终结版(推荐)
Jul 01 PHP
使用php语句将数据库*.sql文件导入数据库
May 05 PHP
PHP使用ob_start生成html页面的方法
Nov 07 PHP
Linux php 中文乱码的快速解决方法
May 13 PHP
微信支付开发动态链接Native支付
Jul 12 PHP
[原创]PHPCMS遭遇会员投稿审核无效的解决方法
Jan 11 PHP
php判断str字符串是否是xml格式数据的方法示例
Jul 26 PHP
laravel在中间件内生成参数并且传递到控制器中的2种姿势
Oct 15 PHP
解决PHPstudy Apache无法启动的问题【亲测有效】
Oct 30 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
咖啡知识大全
2021/03/03 新手入门
PHP的面向对象编程
2006/10/09 PHP
php懒人函数 自动添加数据
2011/06/28 PHP
PHP中使用break跳出多重循环代码实例
2015/01/21 PHP
屏蔽IE弹出&quot;您查看的网页正在试图关闭窗口,是否关闭此窗口&quot;的方法
2013/12/31 Javascript
详解javascript数组去重问题
2015/11/06 Javascript
jQuery+CSS3实现仿花瓣网固定顶部位置带悬浮效果的导航菜单
2016/09/21 Javascript
js 动态生成json对象、时时更新json对象的方法
2016/12/02 Javascript
基于node.js依赖express解析post请求四种数据格式
2017/02/13 Javascript
js通过keyCode值判断单击键盘上某个键,然后触发指定的事件方法
2017/02/19 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
js禁止浏览器的回退事件
2017/04/20 Javascript
Angular 表单控件示例代码
2017/06/26 Javascript
mac中利用NVM管理不同node版本的方法详解
2017/11/08 Javascript
微信小程序使用video组件播放视频功能示例【附源码下载】
2017/12/08 Javascript
基于Vue实现关键词实时搜索高亮显示关键词
2018/07/21 Javascript
JS加密插件CryptoJS实现AES加密操作示例
2018/08/16 Javascript
vue删除html内容的标签样式实例
2018/09/13 Javascript
JS基于对象的链表实现与使用方法示例
2019/01/31 Javascript
基于JS判断对象是否是数组
2020/01/10 Javascript
Python中List.count()方法的使用教程
2015/05/20 Python
Sanic框架流式传输操作示例
2018/07/18 Python
python简单区块链模拟详解
2019/07/03 Python
Python使用微信itchat接口实现查看自己微信的信息功能详解
2019/08/22 Python
python怎么提高计算速度
2020/06/11 Python
美国派对用品及装饰品网上商店:Shindigz
2016/07/30 全球购物
Urban Outfitters美国官网:美国生活方式品牌
2016/08/26 全球购物
波兰珠宝品牌:YES
2019/08/09 全球购物
通信生自我鉴定
2014/01/18 职场文书
旅游网创业计划书
2014/01/31 职场文书
汽车促销活动方案
2014/03/31 职场文书
抗洪救灾先进集体事迹材料
2014/05/26 职场文书
团队口号大全
2014/06/06 职场文书
个人作风纪律整顿整改措施
2014/10/25 职场文书
简历中自我评价范文
2015/03/11 职场文书
工作年限证明模板
2015/06/15 职场文书