溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何理解Constructor Prototype Pattern原型模式

發(fā)布時(shí)間:2021-09-28 17:31:07 來(lái)源:億速云 閱讀:128 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“如何理解Constructor Prototype Pattern原型模式”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“如何理解Constructor Prototype Pattern原型模式”吧!

原型模式中主要角色

抽象原型(Prototype)角色:聲明一個(gè)克隆自己的接口
具體原型(Concrete Prototype)角色:實(shí)現(xiàn)一個(gè)克隆自己的操作

當(dāng)一個(gè)類大部分都是相同的只有部分是不同的時(shí)候,如果需要大量這個(gè)類的對(duì)象,每次都重復(fù)實(shí)例化那些相同的部分是開銷很大的,而如果clone之前建立對(duì)象的那些相同的部分,就可以節(jié)約開銷。

針對(duì)php的一種實(shí)現(xiàn)方式就是__construct()和initialize函數(shù)分開分別處理這個(gè)類的初始化,construct里面放prototype也就是公共的部分,initialize里面是每個(gè)對(duì)象特殊的部分。這樣我們先建立一個(gè)類不initialize,以后每次clone這個(gè)類再進(jìn)行initialize就可以了。

一、引入

  在zf2的model里面有一個(gè)albumTable類,相當(dāng)于一個(gè)操作數(shù)據(jù)庫(kù)動(dòng)作的助手類,里面用到了tablegateway。

  為了每次初始化albumtable都是相同的一個(gè)類,將初始化工作放到了根目錄的module.php文件的getServiceConfig(),其中用到工廠模式,并且通過(guò)回調(diào)函數(shù),當(dāng)每次ServiceManager($sm)需要實(shí)例化一個(gè)對(duì)象的時(shí)候會(huì)自動(dòng)調(diào)用創(chuàng)建一個(gè)alumTable。下面代碼我們可以看出,創(chuàng)建一個(gè)albumTable還需要用相同的方式創(chuàng)建一個(gè)AlbumTableGateWay,這個(gè)類就用到了我們所要講的原型模式。

二、代碼詳解

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());//這個(gè)就是一個(gè)不變的原型
          return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);//傳入到TableGateWay的構(gòu)造函數(shù)中去
        },
      ),
    );
  }

注意并不是TableGateWay運(yùn)用了原型模式而是ResultSet這個(gè)類運(yùn)用了。每當(dāng)tablegateway調(diào)用select()或者insert()等方法的時(shí)候都會(huì)建立一個(gè)ResultSet用來(lái)表示結(jié)果,這些ResultSet中公共部分被clone,而獨(dú)特的部分類如data就會(huì)被initialize。

三、更多代碼示例

  為了更清晰得了解這個(gè)原型,我們先拋開zend這個(gè)大框架,看一個(gè)完整的代碼示例。示例來(lái)自

<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>

這篇文章關(guān)于prototype pattern的部分前半部分其實(shí)是混雜怎樣在構(gòu)造函數(shù)中運(yùn)用繼承來(lái)提高擴(kuò)展性,兩個(gè)模式看起來(lái)可能不太好理解,我們直接看最后的代碼關(guān)于prototype pattern的部分。

<?php
//框架中很常見(jiàn)的adapter類,用來(lái)適配各種數(shù)據(jù)庫(kù),封裝一些基本數(shù)據(jù)庫(kù)連接操作。
//相當(dāng)于上面代碼中的adapter類
class DbAdapter {
  public function fetchAllFromTable($table) {
    return $arrayOfData;
  }
}
//運(yùn)用prototype pattern的類,注意construct和initialize是分開的
//相當(dāng)于上面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() {}
}
//相當(dāng)于上面代碼中的TableGateway類,關(guān)于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;
  }
}

這幾個(gè)類其實(shí)和上面zend代碼中的類是對(duì)應(yīng)的

Dbadapter -- adpater

RowGateWay -- ResultSet

UserRepository - TableGateWay

具體看代碼中的注釋。

這里的RowGateWay可以很明顯的看出在getusers中需要大量的實(shí)例化,那么原型模式就是很必要的了。

下面是運(yùn)用這個(gè)類的代碼

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

到此,相信大家對(duì)“如何理解Constructor Prototype Pattern原型模式”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI