什麼是原型模式
原型模式是先創建好一個原型對象,然後通過clone原型對象來創建新的對象。適用於大對象的創建,因爲創建一個大對象需要很大的開銷,如果每次new就會消耗很大,原型模式僅需內存拷貝即可。
角色分析:
- Prototype(抽象原型角色):聲明一個克隆自身的接口
- Concrete Prototype(具體原型角色):實現一個克隆自身的操作
拷貝對象的兩種方式
淺拷貝:
被拷貝對象的所有變量都含有與原對象相同的值,而且對其他對象的引用仍然是指向原來的對象。
即 變量之間是地址傳遞的;對象之間同時指向一個地址,大家共享一個地址。
賦值時,引用賦值,相當於取了一個別名。對其中一個修改,會影響另一個。
深拷貝:
被拷貝對象的所有的變量都含有與原來對象相同的值,除了那些引用其他對象的變量。那些引用其他對象的變量將指向一個被拷貝的新對象,而不再是原有那些被引用對象。
即 變量被複制了一份,值傳遞,深拷貝把要拷貝的對象所引用的對象也都拷貝了一次,而這種對被引用到的對象拷貝叫做間接拷貝。
賦值時值完全複製,完全的copy,對其中一個作出改變,不會影響另一個。
深拷貝要深入到多少層,是一個不確定的問題。
在決定以深拷貝的方式拷貝一個對象的時候,必須決定對間接拷貝的對象是採取淺拷貝還是深拷貝還是繼續採用深拷貝。
因此,在採取深拷貝時,需要決定多深纔算深。此外,在深拷貝的過程中,很可能會出現循環引用的問題。
利用序列化來做深拷貝:
利用序列化來做深拷貝,把對象寫到流裏的過程是序列化(Serilization)過程,但在業界又將串行化這一過程形象的稱爲“冷凍”或“醃鹹菜”過程;而把對象從流中讀出來的過程則叫做反序列化(Deserialization)過程,也稱爲“解凍”或“回鮮”過程。
在PHP中使用serialize和unserialize函數實現序列化和反序列化。
區別:
淺拷貝是拷貝一層,深層次的對象級別的就拷貝引用;深拷貝是拷貝多層,每一級別的數據都會拷貝出來。
應用場景
需要的對象已經創建過,可考慮複製、克隆對象,避免再次創建對象。
PHP 代碼實現
<?php
/**
* 原型模式
* Class Prototype
*/
abstract class Prototype
{
/**
* 克隆對象
* @param bool|false $isDeep 是否深拷貝 true 深拷貝,false 淺拷貝
* @return mixed
*/
abstract public function cloned($isDeep = false);
}
/**
* 具體原型類
* Class Plane
*/
class Plane extends Prototype
{
public $color;
public function Fly()
{
echo "飛機飛啊飛!" . $this->color . '<br/>';
}
/**
* 具體實現拷貝方法
* @param bool|false $isDeep 是否深拷貝 true 深拷貝,false 淺拷貝
* @return mixed|Plane
*/
public function cloned($isDeep = false)
{
//深拷貝
if($isDeep){
$serialize_obj = serialize($this);
$clone_obj = unserialize($serialize_obj);
return $clone_obj;
}
//淺拷貝
return clone $this;
}
}
//=======================原型模式測試===============================
$plane1 = new Plane();
$plane1->color = "Blue";
$plane2 = $plane1->cloned(true);
$plane1->Fly();
$plane2->Fly();
//結果
//飛機飛啊飛!Blue
//飛機飛啊飛!Blue