原型模式:用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
浅拷贝:被拷贝对象的所有变量都含有与原对象相同的值,而且对其他对象的引用仍然是指向原来的对象,即浅拷贝只负责当前对象实例,对引用的对象不做拷贝。
深拷贝:被拷贝对象的所有的变量都含有与原来对象相同的值,除了那些引用其他对象的变量,那些引用其他对象的变量将指向一个被拷贝的新对象,而不再是原来那些被引用的对象。即深拷贝把要拷贝的对象所引用的对象也拷贝了一次。而这种对被引用到的对象拷贝叫做间接拷贝。
序列化深拷贝:利用序列化来做深拷贝,把对象写到流里的过程是序列化的过程,这一过程称为“冷冻”或“腌咸菜”,反序列化对象的过程叫做“解冻”或“回鲜”。
案例:
\Libs\Prototype.php
1 <?php 2 namespace Libs; 3 4 interface Prototype 5 { 6 public function shallowCopy(); 7 public function deepCopy(); 8 }
\Libs\ConcretePrototype.php
1 <?php 2 namespace Libs; 3 4 class ConcretePrototype implements Prototype 5 { 6 private $_name; 7 public function __construct($name) 8 { 9 $this->_name = $name; 10 } 11 12 public function setName($name) 13 { 14 $this->_name = $name; 15 } 16 public function getName() 17 { 18 return $this->_name; 19 } 20 /** 21 * 浅拷贝 22 * */ 23 public function shallowCopy() 24 { 25 26 return clone $this; 27 28 } 29 /** 30 * 深拷贝 31 * */ 32 public function deepCopy() 33 { 34 $serialize_obj = serialize($this); 35 $clone_obj = unserialize($serialize_obj); 36 return $clone_obj; 37 } 38 }
\Libs\UsePrototype.php
1 <?php 2 namespace Libs; 3 4 class Demo 5 { 6 public $string; 7 } 8 class UsePrototype 9 { 10 public function shallow() 11 { 12 $demo = new Demo(); 13 $demo->string = "susan"; 14 $object_shallow_first = new ConcretePrototype($demo); 15 $object_shallow_second = $object_shallow_first->shallowCopy(); 16 17 var_dump($object_shallow_first->getName()); 18 echo '<br/>'; 19 var_dump($object_shallow_second->getName()); 20 echo '<br/>'; 21 22 $demo->string = "sacha"; 23 var_dump($object_shallow_first->getName()); 24 echo '<br/>'; 25 var_dump($object_shallow_second->getName()); 26 echo '<br/>'; 27 28 } 29 30 public function deep() 31 { 32 $demo = new Demo(); 33 $demo->string = "Siri"; 34 $object_deep_first = new ConcretePrototype($demo); 35 $object_deep_second = $object_deep_first->deepCopy(); 36 37 var_dump($object_deep_first->getName()); 38 echo '<br/>'; 39 var_dump($object_deep_second->getName()); 40 echo '<br/>'; 41 42 $demo->string = "Demo"; 43 var_dump($object_deep_first->getName()); 44 echo '<br/>'; 45 var_dump($object_deep_second->getName()); 46 echo '<br/>'; 47 48 } 49 50 }
调用:
1 $up = new \Libs\UsePrototype; 2 $up->shallow(); 3 echo '<hr>'; 4 $up->deep();
结果:
1 object(Libs\Demo)#2 (1) { ["string"]=> string(5) "susan" } 2 object(Libs\Demo)#2 (1) { ["string"]=> string(5) "susan" } 3 object(Libs\Demo)#2 (1) { ["string"]=> string(5) "sacha" } 4 object(Libs\Demo)#2 (1) { ["string"]=> string(5) "sacha" } 5 6 object(Libs\Demo)#4 (1) { ["string"]=> string(4) "Siri" } 7 object(Libs\Demo)#5 (1) { ["string"]=> string(4) "Siri" } 8 object(Libs\Demo)#4 (1) { ["string"]=> string(4) "Demo" } 9 object(Libs\Demo)#5 (1) { ["string"]=> string(4) "Siri" }