Notice:php
PHP中,原型設計模式的關鍵是要了解如何使用內置函數__clone()設計模式
抽象原型角色(Prototype):聲明一個克隆自身的接口函數
具體原型角色(ConcretePrototype):實現一個克隆自身的操做this
原型設計模式的目的: 經過克隆以減小實例化對象的開銷,與其實例化新對象,徹底可使用一個已有實例的克隆spa
注意Client類是原型設計模式中不可缺乏的一部分設計
模型:code
若是一個項目要求你建立某個原型對象的多個實例,就可使用原型設計模式對象
原型模式還能夠用來建立一種組織結構,能夠根據實際的組織來建立和填充其中的位置blog
克隆不會啓動構造函數中的動做,可是能夠進行賦值之類的操做,好比$this->act = 'action'
這樣的操做會被執行,可是若是要'print $this->act',那麼這個打印的動做將不會被執行繼承
這就意味着原型設計模式不能依賴於構造函數提供重要的輸出或返回結果
構造函數不要作具體的工做,若是一個類實例化要完成大量初始化,結果每每不靈活,並且這是過渡耦合的設計
並非說構造函數不能根據須要賦值,而是它與模式中其它參與者不一樣,由於它須要向參與者作出請求
使用__clone()函數存在限制,但這些限制可能更有助於完成更好的OOP程序
下面用一個基於OOP的實例來解釋原型模式
<?php // IAcmePrototype abstract class IAcmePrototype { protected $name; protected $id; protected $employeePic; protected $dept; // Dept abstract function setDept($orgCode); abstract function getDept(); // Name public function setName($emName) { $this->name = $emName; } public function getName() { return $this->name; } // ID public function setId($emId) { $this->id = $emId; } public function getId() { return $this->id; } // Name public function setPic($ePic) { $this->employeePic = $ePic; } public function getPic() { return $this->employeePic; } abstract function __clone(); } ?>
<?php // Marketing.php include_once 'IAcmePrototype.php'; class Marketing extends IAcmePrototype { const UNIT = 'Marketing'; //將部門名稱設置爲常量方便在後面客戶端調用 private $sales = "sales"; private $promotion = "promotion"; private $strategic = "stractegic planning"; public function setDept($orgCode) { switch ($orgCode) { case 101: $this->dept = $this->sales; break; case 102: $this->dept = $this->promotion; break; case 103: $this->dept = $this->strategic; break; default: $this->dept = "Unreconized Marketing"; } } public function getDept(){ return $this->dept; } function __clone(){} } ?>
<?php // Client.php function __autoload($class_name) { include $class_name . '.php'; //自動加載這個文件夾下面的全部php文件 } class Client { private $market; private $manage; private $engineer; public function __construct() { $this->makeConProto(); //實例化市場類、管理類、工程類 $Tess = clone $this->market; //將剛實例化的市場類克隆過來 $this->setEmployee($Tess, "Tess Smith", 101, "ts101-1234", "/tess.png"); //設置僱員的信息 $this->showEmployee($Tess); //展現僱員的信息,根據方法所要求的傳遞一個對象進去 $Jacob = clone $this->market; $this->setEmployee($Jacob, "Jacob Jones", 102, "jj101-2234", "/jacob.png"); $this->showEmployee($Jacob); $Ricky = clone $this->manage; $this->setEmployee($Ricky, "Ricky Rodrigues", 203, "rr203-5634", "/ricky.png"); $this->showEmployee($Ricky); $Olivia = clone $this->engineer; $this->setEmployee($Olivia, "Olivia Perez", 302, "op301-1278", "/olivia.png"); $this->showEmployee($Olivia); $John = clone $this->engineer; $this->setEmployee($John, "John Smith", 301, "jj302-1454", "/john.png"); $this->showEmployee($John); } private function makeConProto() { $this->market = new Marketing(); $this->manage = new Management(); $this->engineer = new Engineering(); } private function showEmployee(IAcmePrototype $employeeNow) { $pic = $employeeNow->getPic(); //獲取僱員的圖片路徑 echo "<img src=$pic width='150' height='150'><br/>"; echo $employeeNow->getName() . "<br/>"; echo $employeeNow->getDept() . ":" . $employeeNow::UNIT . "<br>"; echo $employeeNow->getId() . "<p/>"; } private function setEmployee(IAcmePrototype $employeeNow, $nm, $dp, $id, $pic) { //根據傳遞進來的值,設置僱員的姓名、部門、id以及圖片的路徑 //這裏是調用了從父類中繼承過來的方法、以及自身的方法 $employeeNow->setName($nm); $employeeNow->setDept($dp); $employeeNow->setId($id); $employeeNow->setPic("$pic"); } } $worker = new Client(); ?>
上面我省略了engineer類和Management類,你能夠根據Marketing直接複製而後進行修改
PS:本文參考書籍:《Learning PHP設計模式》第2部分第6章