Maison  >  Article  >  développement back-end  >  Explication détaillée du modèle de prototype de constructeur en PHP

Explication détaillée du modèle de prototype de constructeur en PHP

*文
*文original
2017-12-28 15:42:301691parcourir

Le modèle de prototype est un modèle de créateur, caractérisé par le renvoi d'une nouvelle instance en "copiant" une instance existante au lieu de créer une nouvelle instance. Cet article fournira une explication détaillée du mode prototype avec des exemples. J'espère qu'il sera utile à tout le monde.

Rôles principaux dans le modèle de prototype

Rôle de prototype abstrait (Prototype) : déclarer une interface qui se clone
Rôle de prototype concret (Concrete Prototype) : Implémentez vous-même une opération de clonage

Lorsque la majeure partie d'une classe est la même et que seules certaines parties sont différentes, si un grand nombre d'objets de cette classe sont nécessaires, il sera très coûteux d'instancier les mêmes parties à plusieurs reprises à chaque fois, et si vous créez les mêmes parties de l'objet avant le clonage, vous pouvez économiser des frais généraux.

Une méthode d'implémentation pour PHP consiste à ce que les fonctions __construct() et initialize gèrent l'initialisation de cette classe séparément. Le prototype est placé dans construct, qui est la partie publique, et la partie spéciale de chaque objet est placée. en initialisation. De cette façon, nous créons d'abord une classe sans l'initialiser, puis clonons cette classe puis l'initialisons à chaque fois.

Ceci est mentionné dans le manuel officiel du framework zend http://framework.zend.com/manual/2.0/en/user-guide/database-and-models.html, mais ce n'est pas expliqué en détail . Je vais l'expliquer ci-dessous. Analysons

1. Introduction

Il existe une classe albumTable dans le modèle zf2, qui équivaut à une classe assistante pour l'exploitation de la base de données. actions, et tablegateway y est utilisé.

Afin d'initialiser l'albumtable avec la même classe à chaque fois, le travail d'initialisation est placé dans getServiceConfig() du fichier module.php dans le répertoire racine, où le mode usine est utilisé, et via le callback fonction, lorsque le ServiceManager ($sm) Lorsqu'un objet doit être instancié, il sera automatiquement appelé pour créer une alumniTable. Nous pouvons voir dans le code ci-dessous que la création d'un albumTable nécessite également la création d'un AlbumTableGateWay de la même manière. Cette classe utilise le modèle prototype dont nous allons parler.

2. Explication détaillée du code


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的构造函数中去
        },
      ),
    );
  }


Notez que TableGateWay n'utilise pas prototypes Pattern mais la classe ResultSet est utilisée. Chaque fois que tablegateway appelle des méthodes telles que select() ou insert(), un ResultSet sera créé pour représenter le résultat. Les parties communes de ces ResultSets seront clonées et des classes partielles uniques telles que les données seront initialisées.

3. Plus d'exemples de code

Afin de comprendre plus clairement ce prototype, laissons de côté le grand framework de zend et regardons un exemple de code complet. Exemple tiré de

29d1381573989fde6caa3ba7028e54fc Meilleures pratiques du constructeur PHP Et le modèle de prototype5db79b134e9f6b82c0b36e0489ee08ed

La première moitié de cet article sur le modèle de prototype est en fait un mélange de la façon d'utiliser l'héritage dans les constructeurs pour améliorer l'évolutivité. Les deux modèles peuvent ne pas sembler très similaires. C'est facile à comprendre. Regardons directement la partie modèle du prototype du code final.


<?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, &#39;user&#39;)
  }
  public function getUsers() {
    $rows = array();
    foreach ($this->dbAdapter->fetchAllFromTable(&#39;user&#39;) as $rowData) {
      $rows[] = $row = clone $this->rowGatewayPrototype;
      $row->initialize($rowData);
    }
    return $rows;
  }
}


Ces classes correspondent en fait aux classes du code zend ci-dessus

Dbadapter - - adpater

RowGateWay -- ResultSet

UserRepository - TableGateWay

Voir les commentaires dans le code pour plus de détails.

Le RowGateWay ici peut clairement voir qu'un grand nombre d'instanciations sont nécessaires dans les getusers, le mode prototype est donc très nécessaire.

Ce qui suit est le code pour utiliser cette classe


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, &#39;user&#39;)
);
$users = $userRepository->getUsers();
$user = $users[0]; // instance of ReadWriteRowGateway with a specific row of data from the db


Recommandations associées :

Explication détaillée du modèle d'adaptateur des modèles de conception PHP

Explication détaillée du modèle d'itérateur de la conception PHP patterns

Explication détaillée du modèle d'observateur du modèle de conception PHP

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn