1. 程式人生 > >PHP面向物件-原型模式

PHP面向物件-原型模式

原型模式是先建立好一個原型物件,然後通過clone原型物件來建立新的物件。適用於大物件的建立,因為建立一個大物件需要很大的開銷,如果每次new就會消耗很大,原型模式僅需記憶體拷貝即可。

  • 優點
  1. 效能優良。原型模式是在記憶體二進位制流的拷貝,要比直接new一個物件效能好很多,特別是要在一個迴圈體內產生大量的物件時,原型模式可以更好地體現其優點。
  2. 逃避建構函式的約束。這個既是優點也是缺點。
  • 缺點
  1. 配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支援序列化的間接物件,或者引用含有迴圈結構的時候。
  2. 必須實現 Cloneable 介面。
  • 主要解決

在執行期建立和刪除原型。

  • 何時使用
  1. 當一個系統應該獨立於它的產品建立,構成和表示時。
  2. 當要例項化的類是在執行時刻指定時,例如,通過動態裝載。
  3. 為了避免建立一個與產品類層次平行的工廠類層次時。
  4. 當一個類的例項只能有幾個不同狀態組合中的一種時。建立相應數目的原型並克隆它們可能比每次用合適的狀態手工例項化該類更方便一些。
  • 應用場景
  1. 資源優化場景。類初始化需要消耗非常多的資源,這個資源包括資料、硬體資源等。
  2. 效能和安全要求的場景。通過new產生一個物件需要非常繁瑣的資料準備或訪問許可權,則可以使用原型模式。
  3. 一個物件多個修改者的場景。一個物件需要提供給其他物件訪問,而且各個呼叫者可能都需要修改其值時,可以考慮使用原型模式拷貝多個物件供呼叫者使用。
  • 實現
原型介面類:Prototype.php
interface Prototype{  
    public function copy();  
    public function deepCopy();  
}  

ConcretePrototype.php
class ConcretePrototype implements Prototype{  
  
    private $_name;  
    public function __construct($name)  
    {  
        $this->_name = $name;  
    }  
    //淺拷貝  
    public function copy(){  
        return clone $this;  
    }  
// 深拷貝   
    public function deepCopy(){  
        return unserialize(serialize($this));  
    }  
  
    public function getName(){  
        return $this-> _name;  
    }  
  
    public function setName($name){  
        $this->_name = $name;  
    }  
}  
UsePrototype.php
class Demo  {  
    public $string;  
}  
  
class UsePrototype  {  
    public function copy(){  
        $demo = new Demo();  
  
        $demo->string = "copyA";  
        $object_first = new ConcretePrototype($demo);  
        $object_second = $object_first->copy();  
  
        var_dump($object_first->getName());  
        echo '<br/>';  
        var_dump($object_second->getName());  
        echo '<br/>';  
  
        $demo->string = "copyB";  
        var_dump($object_first->getName());  
        echo '<br/>';  
        var_dump($object_second->getName());  
        echo '<br/>';  
  
    }  
  
    public function deepCopy()  {  
        $demo = new Demo();  
        $demo->string = "deepCopyA";  
        $object_first = new ConcretePrototype($demo);  
        $object_second = $object_first->deepCopy();  
  
        var_dump($object_first->getName());  
        echo '<br/>';  
        var_dump($object_second->getName());  
        echo '<br/>';  
  
        $demo->string = "deepCopyB";  
        var_dump($object_first->getName());  
        echo '<br/>';  
        var_dump($object_second->getName());  
        echo '<br/>';  
    }  
}  

測試呼叫
$up = new App\Prototype\UsePrototype;  
$up->copy();  
echo '<hr>';  
$up->deepCopy();  
結果:
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyA" }   
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyA" }   
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyB" }   
object(App\Prototype\Demo)#2 (1) { ["string"]=> string(5) "copyB" }   
-------------------------------------------------------------------------  
object(App\Prototype\Demo)#4 (1) { ["string"]=> string(9) "deepCopyA" }   
object(App\Prototype\Demo)#5 (1) { ["string"]=> string(9) "deepCopyA" }   
object(App\Prototype\Demo)#4 (1) { ["string"]=> string(9) "deepCopyB" }   
object(App\Prototype\Demo)#5 (1) { ["string"]=> string(9) "deepCopyA" }   

淺拷貝:(clone) 被拷貝物件的所有變數都含有與原物件相同的值,而且對其他物件的引用仍然是指向原來的物件,即淺拷貝只負責當前物件例項,對引用的物件不做拷貝。深拷貝把要拷貝的物件所引用的物件也拷貝了一次。