《PHP編程:php示例詳解Constructor Prototype Pattern 原型模式》要點:
本文介紹了PHP編程:php示例詳解Constructor Prototype Pattern 原型模式,希望對您有用。如果有疑問,可以聯系我們。
原型模式中主要角色
PHP編程
抽象原型(Prototype)角色:聲明一個克隆本身的接口
具體原型(Concrete Prototype)角色:實現一個克隆本身的操作PHP編程
當一個類大部分都是相同的只有部分是不同的時候,如果必要大量這個類的對象,每次都重復實例化那些相同的部分是開銷很大的,而如果clone之前建立對象的那些相同的部分,就可以節約開銷.PHP編程
針對php的一種實現方式便是__construct()和initialize函數分開分別處理這個類的初始化,construct里面放prototype也便是公共的部分,initialize里面是每個對象特殊的部分.這樣我們先建立一個類不initialize,以后每次clone這個類再進行initialize就可以了.PHP編程
?在zend framework官方手冊里面提到了這個http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html,但是沒有細講,下面我來闡發一下PHP編程
一、引入PHP編程
在zf2的model里面有一個albumTable類,相當于一個操作數據庫動作的助手類,里面用到了tablegateway.PHP編程
為了每次初始化albumtable都是相同的一個類,將初始化工作放到了根目錄的module.php文件的getServiceConfig(),其中用到工廠模式,并且通過回調函數,當每次ServiceManager($sm)必要實例化一個對象的時候會自動調用創建一個alumTable.下面代碼我們可以看出,創建一個albumTable還必要用相同的方式創建一個AlbumTableGateWay,這個類就用到了我們所要講的原型模式.PHP編程
二、代碼詳解PHP編程
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.PHP編程
三、更多代碼示例PHP編程
為了更清晰得了解這個原型,我們先拋開zend這個年夜框架,看一個完整的代碼示例.示例來自PHP編程
<a >PHP Constructor Best Practices And The Prototype Pattern</a>
PHP編程
這篇文章關于prototype pattern的部門前半部門其實是混雜怎樣在構造函數中運用繼承來提高擴展性,兩個模式看起來可能不太好理解,我們直接看最后的代碼關于prototype pattern的部門.PHP編程
<?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代碼中的類是對應的PHP編程
Dbadapter -- adpaterPHP編程
RowGateWay -- ResultSetPHP編程
UserRepository - TableGateWayPHP編程
具體看代碼中的注釋.PHP編程
這里的RowGateWay可以很明顯的看出在getusers中需要大量的實例化,那么原型模式就是很需要的了.PHP編程
下面是運用這個類的代碼PHP編程
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培訓學院每天發布《PHP編程:php示例詳解Constructor Prototype Pattern 原型模式》等實戰技能,PHP、MYSQL、LINUX、APP、JS,CSS全面培養人才。