包括如下五種:php
抽象工廠css
生成器html
工廠方法設計模式
原型編輯器
單例this
咱們選擇工廠方法和原型模式做爲將用PHP實現的建立型設計的例子
工廠方法模式是這5個設計模式中惟一的一種類設計模式
原型模式屬於對象類模式,可使用PHP_clone方法實現。首先基於原型實例化(建立)一個對象,而後由這個實例化對象進一步克隆其餘對象
使用建立型模式時,最有意思的是,當程序和系統愈來愈依賴於對象組合而不是依賴於類繼承時,建立型模式中的程序變成由對象構成的系統,而對象又由其餘對象組合而成,因此任何單個對象的建立都不該該依賴於建立者spa
概念:工廠方法模式就是要建立某種東西,對於工廠方法模式,要建立的東西是一個產品,這個產品與建立它的類之間不存在綁定,爲了保持這種鬆耦合,客戶會經過一個工廠發出請求,再由工廠建立所請求的產品。利用工廠方法模式,請求者發出請求,而不具體建立產品。
什麼時候使用:若是實例化對象的子類可能變化,就要使用工廠方法模式
Why:對象的數目和類型都是未知的,一個類沒法預計它要建立的對象數目,因此你不但願類與它要建立的類緊密綁定設計
案例模型:
code
步驟:orm
第一步是創建工廠:Creator接口
<?php //Creator.php abstract class Creator{ protected abstract function factoryMethod(); public function startFactory(){ $mfg = $this->factoryMethod(); return $mfg; } } ?>
注意到,僞代碼註釋提示startFactory()方法須要返回一個產品(product),在實現中startFactory()但願factoryMethod()返回一個產品對象,因此,factoryMethod()的具體實現要構建並返回由一個按Product接口實現的產品對象
下面有兩個工廠類擴展了Creator,並實現了factoryMethod()方法,factoryMethod()實現經過一個Product方法(getProperties())返回一個文本或圖像產品,TextFactory和GraphicFactory實現中加入了這些內容
<?php //TextFactory.php include_once('Creator.php'); include_once('TextProduct.php'); class TextFactory extends Creator{ protexted function factoryMethod(){ $product = new TextProduct(); return ($product->getProperties()); } } ?>
<?php //TextFactory.php include_once('Creator.php'); include_once('GraphicProduct.php'); class GraphicFactory extends Creator{ protexted function factoryMethod(){ $product = new GraphicProduct(); return ($product->getProperties()); } } ?>
工廠方法設計模式中的第二個接口是Product。因爲這是第一個實現,也是最簡單的實現,全部文本和圖像屬性都只實現一個方法getProperties():創建方法而無屬性,咱們能夠明確想要用這個方法作什麼(好比能夠有個返回值),只要方法名和可見性與簽名一致就不會有問題
<?php //Product.php interface Product{ public function getProperties(); } ?>
能夠利用這個實現,使得同一個方法getProperties()多態,分別返回圖像和文字,以下所示
<?php //TextProduct.php include_once('Prouduct.php'); class TextProduct implements Product{ private $mfgProduct; public function getProperties(){ $this->mfgProduct = "This is a Text<br"; return $this->mfgProduct; } } ?>
<?php //Graphic.php include_once('Product.php'); class GraphicProduct implements Product{ private $mfgProduct; public function getProperties(){ $this->mfgProduct = "This is a Graphic<br>"; return $this->mfgProduct; } } ?>
上面你看到的This is a Graphic以及This is text,能夠替換成你想放入的其它東西,工廠設計會建立這個對象,並把它返回給Client來使用。
這兩個工廠和產品分別覆蓋了抽象方法,來建立兩個不一樣的工廠和產品,它們都符合所實現的接口
客戶
這個模式最後一個參與者是隱含的(上面模型圖中顏色較淡的框):客戶。咱們並不但願Client類直接作出產品請求。實際上,咱們但願可以經過Creator接口作出請求,這樣一來,若是之後咱們增長產品或者工廠,客戶能夠作一樣的請求來獲得更多類型的產品,而不會破壞這個應用
<?php //Client.php include_once('GraphicFactory.php'); include_once('TextFactory.php'); class Client{ private $someGraphicObject; private $someTextObject; public function __construct(){ $this->someGraphicObject = new GraphicFactory(); echo $this->someGraphicObject->startFactory(); $this->someTextObject = new TextFactory(); echo $this->someTextObject->startFactory(); } } $worker = new Client(); ?>
注意Client對象並無向產品直接作出請求,而是經過工廠來請求,重要的是,客戶並不實現產品特性,而留給產品實現來體現。
在本章有個例子,是對上面代碼的改進,也能夠稱做是在工廠中修改產品,可是本猿覺得,例子彷佛舉的不是很好,它把Html代碼嵌套在php代碼中,放在了產品類下的getProperties方法中,以供客戶調用的時候返回,因此我我的以爲這種方法不是很好,一大段代碼放在php中,也不方便編輯器編輯。設計模式是爲了加快開發速度,這樣的方法我拔苗助長。做者是專家,可能也有出於其它考慮。不過裏面有一個觀點我仍是贊成的,其中有一個輔助類的觀點。
所謂輔助類,就是把一些任務給一個單獨的對象來處理,而不是結合到某個參與者中。相似地,若是須要重用一組HTML標記,能夠把它們打包到另外一個對象中以便重用。下面是一個例子
<?php class FormatHelper{ private $topper; private $bottom; public function addTop(){ $this->topper = "<!doctype html><html><head> <link rel='stylesheet' type='text/css' href='products.css'/> <meta charset='UTF-8'> <title>Map Factory</title> </head> <body>"; return $this->topper; } public function closeUp(){ $this->bottom = "</body></html>"; return $this->bottom; } } ?>
上圖與以前的類圖不一樣,它們完成一樣的目標,不過它們的實現有所不一樣。這就是參數化工廠方法設計模式(上圖)與通常的工廠方法設計模式(原類圖)的主要區別之一,即客戶包含工廠和產品的引用。在參數化請求中,Client類必須指定產品,而不僅是產品工廠,factoryMethod()操做中的參數是由客戶傳入的一個產品,因此客戶必須指出它想要的具體產品,不過,這個請求仍然經過Creator接口發出,因此,儘管客戶包含一個產品引用,但經過Creator,客戶仍與產品分離
對於大多數請求,參數化工廠方法更爲簡單,由於客戶只須要處理一個具體工廠,工廠方法操做有一個參數,指示須要建立的產品。而在原來的設計中,每一個產品都有本身的工廠,不須要另外傳遞參數,產品實現依賴於各個產品的特定工廠。
要從參數化工廠方法設計模式實現多個產品,只需使用Product接口實現多個具體產品,另外,因爲具體產品要同時包含文本和圖像,因此在這個例子中,並非分別有這兩個單獨的產品,能夠創建一個類,將文本和圖像做爲一個贊成的實體來處理,這並不違反單一職責原則,即每一個類應當只有一個職責。對於這個類來講,這個單一職責就是顯示描述一個區域的文本和圖像
新工廠與原來的工廠相似,不過它們還包含一個參數和代碼提示。
<?php //Creator.php abstract class Creator{ protected abstract function factoryMethod(Product $product); public function doFactory($productNow){ $countryProduct = $productNow; $mfg = $this->factoryMethod($countryProduct); return $mfg; } } ?>
新的Creator抽象類中能夠看到,factoryMethod()和startFactory操做都須要一個參數。另外代碼提示只是了一個Product對象,而不是Prodcut一個特定實現,因此能夠接受Product的任何具體實例,下面來看看具體的建立者CountryFactory
<?php //CountryFactory.php include_once('Creator.php'); inlcude_once('Product.php'); class CountryFactory extends Creator{ private $country; protected function factoryMethod(Product $product){ $this->country = $product; return ($this->country->getProperties()); } } ?>
這個具體建立者包含一個私有變量$country,其中包含客戶請求的特定產品,它再使用Product方法getProperties()將產品返回給客戶
與試圖讓任意數目的類和對象都保持不變相比,保持接口不變要容易得多。正是由於這個緣由,使用工廠方法模式能夠簡化複雜的建立過程,關鍵就在於它在維持一個公共接口。
本文參考書籍:《Learnig PHP設計模式》第2部分第5章