PHP语言之Constructor Prototype Pattern 原型模式详解
小标 2018-08-02 来源 : 阅读 1343 评论 0

摘要:本文主要向大家介绍了PHP语言之Constructor Prototype Pattern 原型模式详解,通过具体的内容向大家展示,希望对大家学习php语言有所帮助。

本文主要向大家介绍了PHP语言之Constructor Prototype Pattern 原型模式详解,通过具体的内容向大家展示,希望对大家学习php语言有所帮助。

原型模式是一种创建者模式,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。本文将针对原型模式进行实例详解,希望对大家有所帮助。

原型模式中主要角色

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

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

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

在zend framework官方手册里面提到了这个//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="//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频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved