原型模式中主要角色
抽象原型(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的部分。
<"htmlcode">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 原型模式,希望大家喜欢。