原型模式
原型模式(Prototype Pattern),通过复制一个已存在对象来生成一个新对象,被复制的对象称为原型。
优点:不采用new来创建对象,new会消耗较大,原型模式只需要拷贝内存即可。
原型模式的复制又可分为两种:深拷贝和浅拷贝。
深拷贝是通过拷贝内存(包括引用的对象)实现对象的创建,不仅会拷贝类的基本类型的属性和方法,也会拷贝类中引用的其它类的对象。
浅拷贝则会拷贝类的基本类型的属性和方法,对于引用的对象,只会拷贝引用的值。
深拷贝可以通过将对象序列化成字节流,再反序列化来实现;浅拷贝则可直接运用clone方法(在php中)。
角色:1)抽象原型角色;2)具体实现原型角色。
应用场景:
需要创建一个复杂的、构造耗时很多的对象,且已有一个同类对象的时候。
消费者不关心对象构造过程的时候。
如 :工作流实例的重建、复杂数据实体的复制。
以下实例详细描述了如何使用原型模式进行深拷贝和浅拷贝,以及最后的效果如何,使用php编写。
1 <?php 2 /* 3 * 原型模式示例 4 */ 5 error_reporting(E_ALL); 6 ini_set('display_errors','on'); 7 8 /* 9 * 抽象接口类 10 * 包括深拷贝和浅拷贝方法,使得实现它的类都可以实现 11 */ 12 interface Prototype{ 13 public function shadowCopy();//浅拷贝 14 public function deepCopy();//深拷贝 15 } 16 17 /* 18 * 需要引用的对象的类Person 19 */ 20 class Person{ 21 public $name; 22 public function __construct($name) { 23 $this->name = $name; 24 } 25 public function getName(){ 26 return $this->name; 27 } 28 } 29 30 /* 31 *原型类 32 */ 33 class Demo implements Prototype{ 34 private $person; 35 public function __construct($person) { 36 $this->person = $person; 37 } 38 public function setPerson($person){ 39 $this->person = $person; 40 } 41 public function getPerson(){ 42 return $this->person; 43 } 44 public function shadowCopy() { 45 return clone $this; 46 } 47 public function deepCopy() { 48 $serializeObj = serialize($this); 49 $cloneObj = unserialize($serializeObj); 50 return $cloneObj; 51 } 52 private function __clone() { 53 echo "come here when clone"; 54 } 55 } 56 57 $person = new Person("Mary"); 58 $demoObj = new Demo($person); 59 $shadowCopyObj = $demoObj->shadowCopy(); 60 $deepCopyObj = $demoObj->deepCopy(); 61 62 //复制后,原型对象,深拷贝对象,浅拷贝对象中的引用对象值一致 63 var_dump($demoObj->getPerson()->getName()).PHP_EOL;//string(4) "Mary" 64 var_dump($shadowCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Mary" 65 var_dump($deepCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Mary" 66 67 //更改原型对象的引用对象中的值后,原型对象和浅拷贝对象因为引用地址一样都改变,深拷贝对象不变 68 $person->name = "Jack"; 69 var_dump($demoObj->getPerson()->getName()).PHP_EOL;//string(4) "Jack" 70 var_dump($shadowCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Jack" 71 var_dump($deepCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Mary" 72 73 //更换原型对象的引用对象后,原型对象再次改变,浅拷贝对象因为引用地址没有改变所以不变,深拷贝对象不受影响还是保持最开始的值 74 $person2 = new Person("Peter"); 75 $demoObj->setPerson($person2); 76 var_dump($demoObj->getPerson()->getName()).PHP_EOL;//string(4) "Peter" 77 var_dump($shadowCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Jack" 78 var_dump($deepCopyObj->getPerson()->getName()).PHP_EOL;//string(4) "Mary" 79 80 ?>
参考文档: