原型设计模式(Prototype Design Pattern)很有意思, 因为它使用了一种克隆技术来复制实例化的对象. 新对象是通过复制原型实例来创建的. 在这里, 实例是批实例化的具体类.原型设计模式的目的是通过使用克隆来减少实例化对象的开销.与其从一个类实例化新对象, 完全可以使用一个已有实例的克隆.
克隆函数
PHP中使用原型设计模式的关键是要了解如何使用内置函数__clone().
<?php abstract class CloneObject { public $name; public $picture; abstract function __clone(); } class Boy extends CloneObject { public function __construct() { $this->face = "handsome"; $this->name = "chenqionghe"; } public function display() { echo 'look : '.$this->face;; echo '<br />'.$this->name.'<br />'; } public function __clone() {} } $boy = new Boy(); $boy->display(); $cloneBoy = clone $boy; $cloneBoy->face = "still handsome"; $cloneBoy->display();
运行结果如下
look : handsome
chenqionghe
look : still handsome
chenqionghe
$cloneBoy实例是通过克隆Boy的实例$boy, 它可以像$boy一样访问相同的属性, 而且像Boy类的直接实例一样改变这些属性.
注意: 对于所克隆的实例 , clone关键字会为该实例的类实例化另一个实例(使用克隆关键字可以创建一个类的副本, 如果可能, 会自动调用对象的__clone方法, 但不能直接调用 对象的__clone方法), 关于过程, 有一点需要注意的是, 克隆不会不会启动构造函数中的动作.
简单的原型例子
我们以研究果蝇为例.研究的目标是建立一个原型果蝇, 然后一旦出现变异, 就构建这个变异果蝇
抽象类接口和具体实现
原型(IPrototype)的两个具体类实现分别表示不同性别的果蝇, 包括性别变量(gender)和不同性别的和行为.
IPrototype.php
<?php abstract class IPrototype { public $eyeColor; public $winBeat; public $unitEypes; abstract function __clone(); }
IPrototype的这两个实现的区别体现在性别上, 性别用常量标识, 一个是MALE,另一个是FEMAIL.雄果蝇有一个$mated布尔变量, 雄果蝇交配后,这个布尔变量会设置为true, 雌果蝇有一个$fecundity变量,其中包含一个数字值, 表示这只雄果蝇的繁殖能力(产卵个数):
MaleProto.php
<?php include_once('IPrototype.php'); class MaleProto extends IPrototype { const gender = "MALE"; public $mated; public function __construct() { $this->eyeColor = "red"; $this->winBeat = "220"; $this->unitEypes = "760"; } public function __clone(){} }
FemaleProto.php
<?php include_once('IPrototype.php'); class FemaleProto extends IPrototype { const gender = "FEMAIL"; public $fecundity; public function __construct() { $this->eyeColor = "red"; $this->winBeat = "220"; $this->unitEypes = "760"; } public function __clone(){} }
客户
在原型设计模式中,Clien类确实是一个不可缺少的部分.原因在于, 尽管要将子类具体实现作为实例的模板,但使用相同的模板克隆实例的具体工作是由Client类完成的
Client.php
<?php function __autoload($class_name) { include_once $class_name.'.php'; } class Client { //用于直接实例化 private $fly1; private $fly2; //用于克隆 private $c1Fly; private $c2Fly; private $updatedCloneFly; public function __construct() { //实例化 $this->fly1 = new MaleProto(); $this->fly2 = new FemaleProto(); //克隆 $this->c1Fly = clone $this->fly1; $this->c2Fly = clone $this->fly2; $this->updatedCloneFly = clone $this->fly2; //更新克隆 $this->c1Fly->mated = "true"; $this->c2Fly->fecundity = '186'; $this->updatedCloneFly->eyeColor = "purple"; $this->updatedCloneFly->winBeat = "220"; $this->updatedCloneFly->unitEyes = '750'; $this->updatedCloneFly->fecundity = '92'; //通过类型提示方法发送 $this->showFly($this->c1Fly); $this->showFly($this->c2Fly); $this->showFly($this->updatedCloneFly); } private function showFly(IPrototype $fly) { echo "Eye color: ".$fly->eyeColor."<br />"; echo "Wing Beats/second: ".$fly->winBeat."<br />"; echo "Eye units: ".$fly->unitEypes."<br />"; $genderNow = $fly::gender; echo "Gender: ".$genderNow."<br />"; if($genderNow == "FEMAIL") { echo "Number of eggs: ".$fly->fecundity."<hr />"; } else { echo "Mated: ".$fly->mated."<hr />"; } } } $worker = new Client();
运行结果如下
Eye color: red
Wing Beats/second: 220
Eye units: 760
Gender: MALE
Mated: trueEye color: red
Wing Beats/second: 220
Eye units: 760
Gender: FEMAIL
Number of eggs: 186Eye color: purple
Wing Beats/second: 220
Eye units: 760
Gender: FEMAIL
Number of eggs: 92