php示例详解Constructor Prototype Pattern 原型模式


Posted in PHP onOctober 15, 2015

原型模式中主要角色

抽象原型(Prototype)角色:声明一个克隆自己的接口
具体原型(Concrete Prototype)角色:实现一个克隆自己的操作

当一个类大部分都是相同的只有部分是不同的时候,如果需要大量这个类的对象,每次都重复实例化那些相同的部分是开销很大的,而如果clone之前建立对象的那些相同的部分,就可以节约开销。

针对php的一种实现方式就是__construct()和initialize函数分开分别处理这个类的初始化,construct里面放prototype也就是公共的部分,initialize里面是每个对象特殊的部分。这样我们先建立一个类不initialize,以后每次clone这个类再进行initialize就可以了。

 在zend framework官方手册里面提到了这个http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html,但是没有细讲,下面我来分析一下

一、引入

在zf2的model里面有一个albumTable类,相当于一个操作数据库动作的助手类,里面用到了tablegateway。

为了每次初始化albumtable都是相同的一个类,将初始化工作放到了根目录的module.php文件的getServiceConfig(),其中用到工厂模式,并且通过回调函数,当每次ServiceManager($sm)需要实例化一个对象的时候会自动调用创建一个alumTable。下面代码我们可以看出,创建一个albumTable还需要用相同的方式创建一个AlbumTableGateWay,这个类就用到了我们所要讲的原型模式。

二、代码详解

public function getServiceConfig()
  {
    return array(
      'factories' => array(
        'Album\Model\AlbumTable' => function($sm) {
          $tableGateway = $sm->get('AlbumTableGateway');
          $table = new AlbumTable($tableGateway);
          return $table;
        },
        'AlbumTableGateway' => function ($sm) {
          $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
          $resultSetPrototype = new ResultSet();
          $resultSetPrototype->setArrayObjectPrototype(new Album());//这个就是一个不变的原型
          return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);//传入到TableGateWay的构造函数中去
        },
      ),
    );
  }

注意并不是TableGateWay运用了原型模式而是ResultSet这个类运用了。每当tablegateway调用select()或者insert()等方法的时候都会建立一个ResultSet用来表示结果,这些ResultSet中公共部分被clone,而独特的部分类如data就会被initialize。

三、更多代码示例

为了更清晰得了解这个原型,我们先抛开zend这个大框架,看一个完整的代码示例。示例来自

<a href="http://ralphschindler.com/2012/03/09/php-constructor-best-practices-and-the-prototype-pattern">PHP Constructor Best Practices And The Prototype Pattern</a>

这篇文章关于prototype pattern的部分前半部分其实是混杂怎样在构造函数中运用继承来提高扩展性,两个模式看起来可能不太好理解,我们直接看最后的代码关于prototype pattern的部分。

<?php
//框架中很常见的adapter类,用来适配各种数据库,封装一些基本数据库连接操作。
//相当于上面代码中的adapter类
class DbAdapter {
  public function fetchAllFromTable($table) {
    return $arrayOfData;
  }
}
//运用prototype pattern的类,注意construct和initialize是分开的
//相当于上面zend 代码里面的ResultSet类
class RowGateway {
  public function __construct(DbAdapter $dbAdapter, $tableName) {
    $this->dbAdapter = $dbAdapter;
    $this->tableName = $tableName;
  }
  public function initialize($data) {
    $this->data = $data;
  }
  /**
   * Both methods require access to the database adapter
   * to fulfill their duties
   */
  public function save() {}
  public function delete() {}
  public function refresh() {}
}
//相当于上面代码中的TableGateway类,关于gateway可以具体去了解一下。
class UserRepository {
  public function __construct(DbAdapter $dbAdapter, RowGateway $rowGatewayPrototype = null) {
    $this->dbAdapter = $dbAdapter;
    $this->rowGatewayPrototype = ($rowGatewayPrototype) ? new RowGateway($this->dbAdapter, 'user')
  }
  public function getUsers() {
    $rows = array();
    foreach ($this->dbAdapter->fetchAllFromTable('user') as $rowData) {
      $rows[] = $row = clone $this->rowGatewayPrototype;
      $row->initialize($rowData);
    }
    return $rows;
  }
}

这几个类其实和上面zend代码中的类是对应的

Dbadapter -- adpater

RowGateWay -- ResultSet

UserRepository - TableGateWay

具体看代码中的注释。

这里的RowGateWay可以很明显的看出在getusers中需要大量的实例化,那么原型模式就是很必要的了。

下面是运用这个类的代码

class ReadWriteRowGateway extends RowGateway {
  public function __construct(DbAdapter $readDbAdapter, DbAdapter $writeDbAdapter, $tableName) {
    $this->readDbAdapter = $readDbAdapter;
    parent::__construct($writeDbAdapter, $tableName);
  }
  public function refresh() {
    // utilize $this->readDbAdapter instead of $this->dbAdapter in RowGateway base implementation
  }
}
// usage:
$userRepository = new UserRepository(
  $dbAdapter,
  new ReadWriteRowGateway($readDbAdapter, $writeDbAdapter, 'user')
);
$users = $userRepository->getUsers();
$user = $users[0]; // instance of ReadWriteRowGateway with a specific row of data from the db

以上内容是小编给大家介绍的php示例详解Constructor Prototype Pattern 原型模式,希望大家喜欢。

PHP 相关文章推荐
解决php中Cannot send session cache limiter 的问题的方法
Apr 27 PHP
一些 PHP 管理系统程序中的后门
Aug 05 PHP
PHP 多维数组排序(usort,uasort)
Jun 30 PHP
php设计模式 Prototype (原型模式)代码
Jun 26 PHP
基于PHP CURL获取邮箱地址的详解
Jun 03 PHP
解析阿里云ubuntu12.04环境下配置Apache+PHP+PHPmyadmin+MYsql
Jun 26 PHP
PHP JS Ip地址及域名格式检测代码
Sep 27 PHP
PHP中include与require使用方法区别详解
Oct 19 PHP
php强制运行广告的方法
Dec 01 PHP
PHP中实现Bloom Filter算法
Mar 30 PHP
php利用gd库为图片添加水印
Nov 09 PHP
Laravel框架搜索分页功能示例
Feb 01 PHP
PHP经典面试题之设计模式(经常遇到)
Oct 15 #PHP
PHP面试题之文件目录操作
Oct 15 #PHP
php cli配置文件问题分析
Oct 15 #PHP
PHP+Mysql+jQuery实现发布微博程序 php篇
Oct 15 #PHP
10个php函数实用却不常见
Oct 13 #PHP
PHP实现连接设备、通讯和发送命令的方法
Oct 13 #PHP
PHP如何通过传引用的思想实现无限分类(代码简单)
Oct 13 #PHP
You might like
PHP编程与应用
2006/10/09 PHP
透析PHP的配置文件php.ini
2006/10/09 PHP
深入解析php之sphinx
2013/05/15 PHP
PHP设置头信息及取得返回头信息的方法
2016/01/25 PHP
PHP弱类型的安全问题详细总结
2016/09/25 PHP
thinkphp5使html5实现动态跳转的例子
2019/10/16 PHP
jquery事件重复绑定的快速解决方法
2014/01/03 Javascript
javascript 10进制和62进制的相互转换
2014/07/31 Javascript
JS实现的数组全排列输出算法
2015/03/19 Javascript
JavaScript面对国际化编程时的一些建议
2015/06/24 Javascript
微信小程序 wx.request(接口调用方式)详解及实例
2016/11/23 Javascript
微信小程序picker组件下拉框选择input输入框的实例
2017/09/20 Javascript
JS实现点击循环切换显示内容的方法
2017/10/19 Javascript
微信小程序实现跟随菜单效果和循环嵌套加载数据
2017/11/21 Javascript
关于vue单文件中引用路径的处理方法
2018/01/08 Javascript
Angular5中调用第三方js插件的方法
2018/02/26 Javascript
Vue头像处理方案小结
2018/07/26 Javascript
JavaScript设计模式之观察者模式实例详解
2019/01/16 Javascript
简单了解JavaScript作用域
2020/07/31 Javascript
[05:09]第二届DOTA2亚洲邀请赛决赛日比赛集锦:iG 3:0 OG夺冠
2017/04/05 DOTA
python错误:AttributeError: 'module' object has no attribute 'setdefaultencoding'问题的解决方法
2014/08/22 Python
python如何在终端里面显示一张图片
2016/08/17 Python
使用requests库制作Python爬虫
2018/03/25 Python
pandas DataFrame 根据多列的值做判断,生成新的列值实例
2018/05/18 Python
搞清楚 Python traceback的具体使用方法
2019/05/13 Python
postman传递当前时间戳实例详解
2019/09/14 Python
Python3标准库之functools管理函数的工具详解
2020/02/27 Python
keras 回调函数Callbacks 断点ModelCheckpoint教程
2020/06/18 Python
加拿大最大的箱包及旅游配件零售商:Bentley Leathers
2017/07/19 全球购物
澳大利亚波西米亚风情网上商店:Czarina
2019/03/18 全球购物
2014信息技术专业毕业生自我评价
2014/01/17 职场文书
《小猪家的桃花树》教学反思
2014/04/11 职场文书
六一儿童节活动总结
2014/08/27 职场文书
2015年教务主任工作总结
2015/07/22 职场文书
党章党规党纪学习心得体会
2016/01/14 职场文书
vue动态绑定style样式
2022/04/20 Vue.js