每天一記之php原型模式

來源:互聯網
上載者:User
每日一記之php原型模式

原型模式是指通過現有的執行個體通過拷貝得到新的執行個體。

在程式的設計中,有的時候我們去執行個體化某個對象需要做太多的初始化工作,非常耗時的時候,我們可以考慮採用原型模式來得到新的執行個體。

其實在php中我們很容易通過clone關鍵字去實現對象的複製。另外通過魔術方法__clone()指定在clone的時候需要進行的操作。這個其實就是原型模式的實現方式了。當然,有時候為了讓代碼看起來比較優雅,比較完善。我們可以自己去寫相關的實現方式,當然也需要用到clone關鍵字。

name = $name;        $this->startTime = time();    }    public function copy(){        return clone $this;    }}

在這裡我們可以建立一個task

$task1 = new Task("Task1");

現在我們已經有了一個Task的執行個體了,我們要得到一個新的task執行個體就可以通過clone的方法

$task2 = $task1->copy();

可是現在這樣我們列印$task1和$task2的startTime,兩者是一樣的,而我們又希望clone出來的對象時間應該是目前時間,怎麼做呢?所以我們就得去寫__clone方法,該方法在一個對象嘗試進行clone的時候會自動調用。改良後的代碼如下

class Task implements Cloneable{    public $name;    public $startTime;    public function __construct($name){        //這裡執行個體化Task需要做很多工作        $this->name = $name;        $this->startTime = time();    }    public function __clone(){        //在複製的時候把startTime設為目前時間        $this->startTime = time();        //複製的時候需要執行的操作    }    public function copy(){        return clone $this;    }}

這樣複製出來的對象的startTime就更正為目前時間了。

當然了,這隻是一個簡單的原型模式,在實際的複製中,又分為淺複製和深複製。

淺複製: 即對象在調用clone方法時只複製基本的資料類型,而如果對象中包含其他對象的引用時,則copy其他對象的引用

深複製:即除了複製基本的資料類型外,引用的類型的資料也一併複製。


舉個例子,現在我的task類裡面有一個其他對象的引用,比如Parent。相關代碼如下:

class TaskParent{    public $name;    public function __construct($name){        $this->name = $name;    }}class Task implements Cloneable{    public $name;    public $startTime;    public $parent;    public function __construct($name){        //這裡執行個體化Task需要做很多工作        $this->name = $name;        $this->startTime = time();        //這裡直接new一個parent        $this->parent = new TaskParent("do some work");    }    public function __clone(){        //在複製的時候把startTime設為目前時間        $this->startTime = time();        //複製的時候需要執行的操作    }    public function copy(){        return clone $this;    }}

在上面的代碼裡,我們新定義了一個TaskParent的類,然後Task持有該對象的一個引用,用戶端代碼:

$task1 = new Task("Task1");echo $task1->parent->name."\r\n";//clone一個對象$task2 = $task1->copy();echo $task2->parent->name."\r\n";//將task1的parent的name設為另外的值$task1->parent->name = "do another work";//列印task2的parent的值echo $task2->parent->name;
上面的代碼最後一句話將列印 do another work,也就是說我們更改task1的parent影響到了task2。這就是典型的淺複製,如果想實現深複製,則可以進行如下改裝

class Task implements Cloneable{    public $name;    public $startTime;    public $parent;    public function __construct($name){        //這裡執行個體化Task需要做很多工作        $this->name = $name;        $this->startTime = time();        //這裡直接new一個parent        $this->parent = new TaskParent("do some work");    }    public function __clone(){        //在複製的時候把startTime設為目前時間        $this->startTime = time();        //複製parent        $this->parent = clone $this->parent;        //複製的時候需要執行的操作    }    public function copy(){        return clone $this;    }}

我們在__clone方法裡面對parent也進行了一次複製,所以現在列印剛才的代碼就沒有問題了。這就是深複製。

在真實的編碼環境中,可能一個對象持有很多其他的對象的引用,而其他對象對象又持有很多的引用。由於引用的不確定性,我們一開始的時候就應該注意,到底哪些對象需要深複製,那些對象不需要。

如果想實現快速的深複製,網上一哥們提供了一個簡單的方法代碼如下:

class Task implements Cloneable{    public $name;    public $startTime;    public $parent;    public function __construct($name){        //這裡執行個體化Task需要做很多工作        $this->name = $name;        $this->startTime = time();        //這裡直接new一個parent        $this->parent = new TaskParent("do some work");    }    public function __clone(){        //在複製的時候把startTime設為目前時間        $this->startTime = time();        //複製parent        $this->parent = clone $this->parent;        //複製的時候需要執行的操作    }    public function copy(){        //return clone $this;        //這裡不使用clone關鍵字,而是使用序列化和還原序列化來進行        return unserialize(serialize($this));    }}

上述代碼中通過serialize和unserialize來得到新的執行個體,經測試,完全是深複製。關於serialize和unserialize的效率以及具體講解將在以後補充上


  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.