一败晴、簡(jiǎn)介
相比正常創(chuàng)建一個(gè)對(duì)象 (new Foo () )浓冒,首先創(chuàng)建一個(gè)原型,然后克隆它會(huì)更節(jié)省開(kāi)銷尖坤。
原型模式是先創(chuàng)建好一個(gè)原型對(duì)象稳懒,然后通過(guò)clone原型對(duì)象來(lái)創(chuàng)建新的對(duì)象。適用于大對(duì)象的創(chuàng)建慢味,因?yàn)閯?chuàng)建一個(gè)大對(duì)象需要很大的開(kāi)銷场梆,如果每次new就會(huì)消耗很大,原型模式僅需內(nèi)存拷貝即可纯路。
二或油、場(chǎng)景
比如:
- 大量的數(shù)據(jù)對(duì)象(比如通過(guò)ORM獲取1,000,000行數(shù)據(jù)庫(kù)記錄然后創(chuàng)建每一條記錄對(duì)應(yīng)的對(duì)象實(shí)體)
三、類結(jié)構(gòu)
原型模式主要角色如下:
角色 | 類別 | 簡(jiǎn)述 |
---|---|---|
Prototype | 抽象原型角色 | 聲明一個(gè)克隆自身的接口 |
Concrete Prototype | 具體原型角色 | 實(shí)現(xiàn)一個(gè)克隆自身的操作 |
四驰唬、UML圖
五顶岸、代碼分析
1、抽象原型角色
interface Prototype
{
public function shallowCopy();
public function deepCopy();
}
2叫编、具體原型角色
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;
}
}
3辖佣、使用案例
class Demo
{
public $string;
}
class UsePrototype
{
//測(cè)試淺拷貝
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/>';
}
//測(cè)試深拷貝
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();
結(jié)果如下:
object(Demo)#2 (1) { ["string"]=> string(5) "susan" }
object(Demo)#2 (1) { ["string"]=> string(5) "susan" }
object(Demo)#2 (1) { ["string"]=> string(5) "sacha" }
object(Demo)#2 (1) { ["string"]=> string(5) "sacha" }
--------------------------------------------------------------
object(Demo)#5 (1) { ["string"]=> string(4) "Siri" }
object(Demo)#8 (1) { ["string"]=> string(4) "Siri" }
object(Demo)#5 (1) { ["string"]=> string(4) "Demo" }
object(Demo)#8 (1) { ["string"]=> string(4) "Siri" }
注意:在PHP中,對(duì)象本身就是引用傳遞搓逾。
六卷谈、特點(diǎn)
1、淺拷貝
被拷貝對(duì)象的所有變量都含有與原對(duì)象相同的值霞篡,而且對(duì)其他對(duì)象的引用仍然是指向原來(lái)的對(duì)象世蔗。即淺拷貝只負(fù)責(zé)當(dāng)前對(duì)象實(shí)例,對(duì)引用的對(duì)象不做拷貝朗兵。
2污淋、深拷貝
被拷貝對(duì)象的所有的變量都含有與原來(lái)對(duì)象相同的值,除了那些引用其他對(duì)象的變量矛市。那些引用其他對(duì)象的變量將指向一個(gè)被拷貝的新對(duì)象芙沥,而不再是原有那些被引用對(duì)象。
即深拷貝把要拷貝的對(duì)象所引用的對(duì)象也都拷貝了一次浊吏,而這種對(duì)被引用到的對(duì)象拷貝叫做間接拷貝。
3救氯、序列化深拷貝
利用序列化來(lái)做深拷貝找田,把對(duì)象寫(xiě)到流里的過(guò)程是序列化的過(guò)程,這一過(guò)程稱為“冷凍”或“腌咸菜”着憨,反序列化對(duì)象的過(guò)程叫做“解凍”或“回鮮”墩衙。
在PHP中使用serialize和unserialize函數(shù)實(shí)現(xiàn)序列化和反序列化。