The prototype mode is a creator mode, which is characterized by "copying" an existing instance to return a new instance instead of creating a new instance. This article will provide a detailed explanation of the prototype mode with examples. I hope it will be helpful to everyone.
Main roles in the prototype pattern
Abstract prototype (Prototype) role: declare an interface that clones itself
Concrete Prototype (Concrete Prototype) role: Implement an operation of cloning yourself
When most of a class is the same and only some parts are different, if a large number of objects of this class are needed, it will be very expensive to instantiate the same parts repeatedly every time. , and if you create the same parts of the object before cloning, you can save overhead.
One implementation method for PHP is that the __construct() and initialize functions handle the initialization of this class separately. The prototype is placed in construct, which is the public part, and the special part of each object is placed in initialize. In this way, we first create a class without initializing it, and then clone this class and then initialize it every time.
This is mentioned in the zend framework official manual http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html, but it is not explained in detail. I will explain it below. Let’s analyze it
1. Introduction
There is an albumTable class in the zf2 model, which is equivalent to an assistant class for operating database actions, and tablegateway is used in it.
In order to initialize the albumtable with the same class every time, the initialization work is placed in getServiceConfig() of the module.php file in the root directory. The factory mode is used, and through the callback function, each time the ServiceManager ($sm) When an object needs to be instantiated, it will be automatically called to create an alumniTable. We can see from the code below that creating an albumTable also requires creating an AlbumTableGateWay in the same way. This class uses the prototype pattern we are going to talk about.
2. Detailed code explanation
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的构造函数中去 }, ), ); }
Note that TableGateWay does not use the prototype mode. It is the ResultSet class that is used. Whenever the tablegateway calls methods such as select() or insert(), a ResultSet will be created to represent the result. The common parts of these ResultSets are cloned, and unique partial classes such as data will be initialized.
3. More code examples
In order to understand this prototype more clearly, let’s put aside the big framework of zend and look at a complete code example. Example from
PHP Constructor Best Practices And The Prototype Pattern
The first half of this article about prototype pattern is actually a mixture of how to use inheritance in constructors to improve scalability. The two patterns may not seem very similar. It’s easy to understand. Let’s look directly at the prototype pattern part of the final code.
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; } }
These classes actually correspond to the classes in the zend code above
Dbadapter -- adpater
RowGateWay -- ResultSet
UserRepository - TableGateWay
See the comments in the code for details.
The RowGateWay here can clearly see that a large number of instantiations are required in getusers, so the prototype mode is very necessary.
The following is the code to use this class
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
##Related recommendations:
Detailed Explanation of the Adapter Pattern of PHP Design Pattern
Detailed Explanation of the Iterator Pattern of PHP Design Pattern
Detailed explanation of the observer pattern of php design pattern
The above is the detailed content of Detailed explanation of Constructor Prototype Pattern in PHP. For more information, please follow other related articles on the PHP Chinese website!