概念理解:原型模式是先創建好一個原型對象,然后通過clone原型對象來創建新的對象。適用於大對象的創建,因為創建一個大對象需要很大的開銷,如果每次new就會消耗很大,原型模式僅需內存拷貝即可。
主要角色:
Prototype(抽象原型角色):聲明一個克隆自身的接口
Concrete Prototype(具體原型角色):實現一個克隆自身的操作
下面我們觀察源碼:
\Libs\Prototype.php
<?php namespace Libs; interface Prototype { public function shallowCopy(); public function deepCopy(); }
\Libs\ConcretePrototype.php
<?php namespace Libs; class ConcretePrototype implements Prototype { private $_name; public function __construct($name) { $this->_name = $name; } public function setName($name) { $this->_name = $name; } public function getName() { return $this->_name; } /** * 淺拷貝 * */ public function shallowCopy() { return clone $this; } /** * 深拷貝 * */ public function deepCopy() { $serialize_obj = serialize($this); $clone_obj = unserialize($serialize_obj); return $clone_obj; } }
\Libs\UsePrototype.php
<?php namespace Libs; class Demo { public $string; } class UsePrototype { public function shallow() { $demo = new Demo(); $demo->string = "susan"; $object_shallow_first = new ConcretePrototype($demo); $object_shallow_second = $object_shallow_first->shallowCopy(); var_dump($object_shallow_first->getName()); echo '<br/>'; var_dump($object_shallow_second->getName()); echo '<br/>'; $demo->string = "sacha"; var_dump($object_shallow_first->getName()); echo '<br/>'; var_dump($object_shallow_second->getName()); echo '<br/>'; } public function deep() { $demo = new Demo(); $demo->string = "Siri"; $object_deep_first = new ConcretePrototype($demo); $object_deep_second = $object_deep_first->deepCopy(); var_dump($object_deep_first->getName()); echo '<br/>'; var_dump($object_deep_second->getName()); echo '<br/>'; $demo->string = "Demo"; var_dump($object_deep_first->getName()); echo '<br/>'; var_dump($object_deep_second->getName()); echo '<br/>'; } }
調用:
$up = new \Libs\UsePrototype; $up->shallow(); echo '<hr>'; $up->deep();
結果:
object(Libs\Demo)#2 (1) { ["string"]=> string(5) "susan" } object(Libs\Demo)#2 (1) { ["string"]=> string(5) "susan" } object(Libs\Demo)#2 (1) { ["string"]=> string(5) "sacha" } object(Libs\Demo)#2 (1) { ["string"]=> string(5) "sacha" } object(Libs\Demo)#4 (1) { ["string"]=> string(4) "Siri" } object(Libs\Demo)#5 (1) { ["string"]=> string(4) "Siri" } object(Libs\Demo)#4 (1) { ["string"]=> string(4) "Demo" } object(Libs\Demo)#5 (1) { ["string"]=> string(4) "Siri" }
代碼中提到了深拷貝和淺拷貝,那么我們先來分析一下這兩者的區別
淺拷貝:被拷貝對象的所有變量都含有與原對象相同的值,而且對其他對象的引用仍然是指向原來的對象,即淺拷貝只負責當前對象實例,對引用的對象不做拷貝。
深拷貝:被拷貝對象的所有的變量都含有與原來對象相同的值,除了那些引用其他對象的變量,那些引用其他對象的變量將指向一個被拷貝的新對象,而不再是原來那些被引用的對象。即深拷貝把要拷貝的對象所引用的對象也拷貝了一次。而這種對被引用到的對象拷貝叫做間接拷貝。
在決定以深拷貝的方式拷貝一個對象的時候,必須決定對間接拷貝的對象時采取淺拷貝還是深拷貝還是繼續采用深拷貝。
序列化深拷貝:利用序列化來做深拷貝,把對象寫到流里的過程是序列化的過程,這一過程稱為“冷凍”或“腌咸菜”,反序列化對象的過程叫做“解凍”或“回鮮”。
引用與推薦: