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开发负载均衡指南
Jul 17 PHP
php中apc缓存使用示例
Dec 25 PHP
php命令行(cli)下执行PHP脚本文件的相对路径的问题解决方法
May 25 PHP
深入浅析php中sprintf与printf函数的用法及区别
Jan 08 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
Aug 19 PHP
Yii2.0 Basic代码中路由链接被转义的处理方法
Sep 21 PHP
Thinkphp 中 distinct 的用法解析
Dec 14 PHP
ThinkPHP实现登录退出功能
Jun 29 PHP
YII框架模块化处理操作示例
Apr 26 PHP
ThinkPHP框架结合Ajax实现用户名校验功能示例
Jul 03 PHP
ThinkPHP 5.1 跨域配置方法
Oct 11 PHP
自定义Laravel (monolog)日志位置,并增加请求ID的实现
Oct 17 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
中国的第一台收音机
2021/03/01 无线电
非洲第一个咖啡超凡杯大赛承办国—卢旺达的咖啡怎么样
2021/03/03 咖啡文化
php动态生成版权所有信息的方法
2015/03/24 PHP
关于Laravel参数验证的一些疑与惑
2019/11/19 PHP
基于jquery的网页SELECT下拉框美化代码
2010/10/28 Javascript
JQuery验证工具类搜集整理
2013/01/16 Javascript
javaScript arguments 对象使用介绍
2013/10/18 Javascript
快速解决js开发下拉框中blur与click冲突
2016/10/10 Javascript
设置jquery UI 控件的大小方法
2016/12/12 Javascript
一个例子轻松学会Vue.js
2017/01/02 Javascript
原生js实现放大镜效果
2017/01/11 Javascript
Three.js的使用及绘制基础3D图形详解
2017/04/27 Javascript
详解node-ccap模块生成captcha验证码
2017/07/01 Javascript
JS中正则表达式要注意lastIndex属性
2017/08/08 Javascript
jQuery实现表单动态添加数据并提交的方法
2018/07/19 jQuery
vue 中使用 watch 出现了如下的报错的原因分析
2019/05/21 Javascript
小程序多图列表实现性能优化的方法步骤
2019/05/28 Javascript
js实现简单贪吃蛇游戏
2020/05/15 Javascript
js实现金山打字通小游戏
2020/07/24 Javascript
简单谈谈offsetleft、offsetTop和offsetParent
2020/12/04 Javascript
python调用新浪微博API项目实践
2014/07/28 Python
聊聊python里如何用Borg pattern实现的单例模式
2019/06/06 Python
Django 接收Post请求数据,并保存到数据库的实现方法
2019/07/12 Python
TensorFlow基于MNIST数据集实现车牌识别(初步演示版)
2019/08/05 Python
python目标检测给图画框,bbox画到图上并保存案例
2020/03/10 Python
Python xlrd模块导入过程及常用操作
2020/06/10 Python
python爬取2021猫眼票房字体加密实例
2021/02/19 Python
原生 JS+CSS+HTML 实现时序图的方法
2019/07/31 HTML / CSS
介绍一下结构化程序设计方法和面向对象程序设计方法的区别
2012/06/27 面试题
乡镇网格化管理实施方案
2014/03/23 职场文书
协议书与合同的区别
2014/04/18 职场文书
教师对学生的评语
2014/04/28 职场文书
档案管理员岗位职责
2015/02/12 职场文书
医学生自荐信范文
2015/03/05 职场文书
2016年秋季趣味运动会开幕词
2016/03/04 职场文书
求职信如何撰写?
2019/05/22 职场文书