本文實例講述了PHP設計模式之工廠模式定義與用法。分享給大家供大家參考,具體如下:
工廠模式(Factory Design Pattern)作為一種創建型設計模式, 遵循了開放-封閉原則, 對修改封閉, 對擴展開放. 工廠方法(Factory Method)模式就是要創建"某種東西". 對于工廠方法模式, 要創建的"東西"是一個產品,這個產品與創建它的類之間不存在綁定.實際上,為了保持這種松耦合,客戶會通過一個工廠發出請求. 再由工廠創建所請求的產品.也可以換種方式考慮, 利用工廠方法模式, 請求者只發出請求, 而不具體創建產品.
工廠的工作
先建立一個工廠的接口
Factory.php
<?php abstract class Factory { //抽象的創建對象的方法 protected abstract function createProduct(); //該方法調用createProduct方法返回一個產品對象. public function start() { return $this->createProduct(); } }
start
方法返回一個產品,該方法調用createProduct
方法完成產生產品的操作.所以createProduct的具體實現要構建并返回一個按Product接口實現的產品對象.
比如產品都有一個共同的方法getProperties()
, 以下是對應Product接口
Product.php
<?php //產品接口 interface Product { public function getProperties(); }
接著, 我們要建立兩個工廠,文本工廠TextFactory和圖像工廠phptoFactory
TextFactory.php
<?php include_once('Factory.php'); include_once('TextProduct.php'); class TextFactory extends Factory { protected function createProduct() { $product = new TextProduct(); return $product->getProperties(); } }
PhotoFactory.php
<?php include_once('Factory.php'); include_once('PhotoProduct.php'); class PhotoFactory extends Factory { protected function createProduct() { $product = new PhotoProduct(); return $product->getProperties(); } }
可以看到,在工廠方法的實現中, getProperties方法引入了多態(polymorphism), 將用這個方法返回"文本"或"圖像". 同一個getProperties()
有多個(poly)不同的形態(morphs), 這就是多態.在這種情況下, 其中一種形式返回文本, 而另一種返回圖像.
可以在properties這個實現中放入你想要的任何東西,工廠方法設計將會創建這個對象, 并把他返回給Client使用.
下面的是兩個產品的實現
TextProduct.php
<?php include_once('Product.php'); class TextProduct implements Product { public function getProperties() { return "這里是文本產品"; } }
PhotoProduct.php
<?php include_once('Product.php'); class PhotoProduct implements Product { //這是產品具有的方法 public function getProperties() { return "這里是圖像產品"; } }
這兩個產品實現了Product接口中的抽象方法getProperties()
,
客戶(Client)
我們并不希望客戶直接做出產品請求.實際上, 我們希望客戶通過Factory工廠接口做出請求.這樣一來,如果以后我們增加了產品或者工廠, 客戶可以做同樣的請求來得到更多類型的產品 , 而不會破壞這個應用:
Client.php
<?php include_once('PhotoFactory.php'); include_once('TextFactory.php'); class Client { public function __construct() { $this->somePhotoObject = new PhotoFactory(); echo $this->somePhotoObject->start() . '<br />'; $this->someTextObject = new TextFactory(); echo $this->someTextObject->start() . '<br />'; } } $worker = new Client();
運行Client.php, 得到下面的結果
這里是圖像產品
這里是文本產品
注意: Client對象并沒有向產品直接做出請求, 而是通過工廠來請求. 重要的是, 客戶并不實現產品特性, 而留給產品實現來體現.
調整產品
設計模式的真正價值并不是提高操作的速度, 而是加快開發的速度.
如果現在需求變化了, 需要對圖像產品做出修改, 只需要修改相應的產品PhotoProduct的getProperties方法即可
對象的改變看起來很簡單 不過Product的getProperties()
方法仍保持相同的接口,請求工廠返回一個屬性對象
增加新產品和參數化請求
問題來了,如果要增加更多的圖像和文本說明, 有沒有必要每次增加一個新的區域就增加一個新的具體的工廠類?這意味著要為每個新區域增加一個新工廠和產品.于是,我們引進了參數化工廠設計模式
參數化工廠設計模式和一般的工廠設計模式的主要區別之一是客戶包含工廠和產品的引用. 在參數化請求中, Client類必須指定產品, 而不是產品工廠. createProduct()
操作中的參數是由客戶傳入一個產品; 所以客戶必須指出它想要的具體產品. 不過, 這個請求仍然是通過工廠接口Factory發出的. 所以, 盡管客戶包含一個產品引用, 但通過Factory, 客戶仍然與產品分離.
一個工廠多個產品(參數化工廠方法)
對于大多數請求, 參數化工廠方法更為簡單, 因為客戶只需要處理一個具體工廠.工廠方法操作有一個參數,指示需要創建的產品.而在原來的設計中, 每個產品都有自己的工廠, 不需要另個傳遞參數; 產品實現依賴于各個產品特定的工廠.
新工廠接口
Factory.php
<?php abstract class Factory { //抽象的創建對象的方法 protected abstract function createProduct(Product $product); //該方法由factoryMethod方法返回一個產品對象. public function start($product) { return $this->createProduct($product); } }
在這個新的Factory接口中可以看到, create()
和start()
都需要一個參數,指定一個Product對象, 而不是Product接口的一個特定實現, 所以可以接受任何Product的具體實例.
工廠具體實現
具體的創建者類CommonFactory實現了createProduct()
,如下
CommonFactory.php
<?php include_once('Factory.php'); include_once('Product.php'); class CommonFactory extends Factory { protected function createProduct(Product $product) { return $product->getProperties(); } }
這個類調用Product的方法getProperties將產品返回給客戶.
新產品
具體產品的變化并不會改變原來的Product接口,還是原來的代碼
<?php //產品接口 interface Product { public function getProperties(); }
例如, 現在有一個鋼筆產品PenProduct
PenProduct.php
<?php include_once('Product.php'); class PenProduct implements Product { public function getProperties() { return "鋼筆產品"; } }
客戶Clent(有參數)
<?php include_once('CommonFactory.php'); include_once('PenProduct.php'); class Client { public function __construct() { $commonFactory = new CommonFactory(); echo $commonFactory->start(new PenProduct()); } } $worker = new Client();
運行后輸出
鋼筆產品
以后如果開發出了新的產品, 只需要創建對應的產品類, 然后客戶指定想要的新產品 , 即可返回客戶需要的產品.
總結:
產品改變: 接口不變
使用設計模式的一大好處就是可以很容易地對類做出改變, 而不會破壞更大的程序. 之所以能夠容易地做出改變, 秘訣在于保持接口不變, 而只改變內容.
希望本文所述對大家PHP程序設計有所幫助。