敏捷软件开发学习笔记(四)之结构型设计模式
PHP結構型設計模式
參考
- 設計模式
- PHP 設計模式全集 2018
什么是結構型是設計模式
結構型模式講的是如何將類和對象按照某種布局組成更大的結構。它分為類結構型模式和對象結構型模式,其中類結構型模式采用繼承機制來組織接口和類,其中對象結構型模式采用組合和聚合來組合對象。由于組合和聚合比繼承的耦合性低,滿足“合成復用原則”,所以對象結構型模式比類結構型模式具有更大的靈活性。
1.適配器設計模式(Adapter模式)
在現實生活中有很多類似的例子,如用直流電的筆記本電腦接交流電源時需要一個電源適配器,用計算機訪問照相機的 SD 內存卡時需要一個讀卡器等。
為什么需要適配器設計模式?
在軟件設計中也可能出現:需要開發的具有某種業務功能的組件在現有的組件庫中已經存在,但它們與當前系統的接口規范不兼容,如果重新開發這些組件成本又很高,這時用適配器模式能很好地解決這些問題。
什么是適配器設計模式?
適配器模式(Adapter)包含以下主要角色。
- 目標(Target)接口:當前系統業務所期待的接口,它可以是抽象類或接口。
- 適配者(Adaptee)類:它是被訪問和適配的現存組件庫中的組件接口。
- 適配器(Adapter)類:它是一個轉換器,通過繼承或引用適配者的對象,把適配者接口轉換成目標接口,讓客戶按目標接口的格式訪問適配者。
即現在想要在 目標接口 中調用 適配者類 中的某些方法,所以定義一個 適配器類 繼承 適配者類,實現目標接口。
分類
適配器模式分為類結構型模式和對象結構型模式兩種,前者類之間的耦合度比后者高,且要求程序員了解現有組件庫中的相關組件的內部結構,所以應用相對較少些。
實例
實例一:使用類結構型模式
第一步:首先需要一個適配者類(已經存在的)
class Adaptee{public function usedMethod(){echo "this is Adaptee method";} }第二步:現在想要開發一個組件(源系統中存在,但是不符合規范)
interface Target{public function request(); }第三步:定義一個適配器類
class Adapter extends Adaptee implements Target{public function request(){$this->usedMethod();} }第四步:使用
$adapter = new Adapter(); $adapter->request();實例二:使用對象結構型模式
前兩個條件與上面相同
第三步:定義一個適配器類
class Adapter implements Target{public $adaptee;public function __construct(Adaptee $adaptee){$this->adaptee = $adaptee;} public function request(){$this->adaptee->usedMethod();} }第四步:使用
$adapter = new Adapter(); $adapter->request(new Adaptee());模式的應用場景
適配器模式(Adapter)通常適用于以下場景。
- 以前開發的系統存在滿足新系統功能需求的類,但其接口同新系統的接口不一致。
- 使用第三方提供的組件,但組件接口定義和自己要求的接口定義不同。
2. 代理模式(Proxy)
在有些情況下,一個客戶不能或者不想直接訪問另一個對象,這時需要找一個中介幫忙完成某項任務,這個中介就是代理對象。例如,購買火車票不一定要去火車站買,可以通過 12306 網站或者去火車票代售點買。又如找女朋友、找保姆、找工作等都可以通過找中介完成。
為什么需要代理模式?
在軟件設計中,如果由于某些原因(如安全)不想訪問真實對象的話,可以使用代理模式。
什么是代理模式?
代理模式主要分為以下幾個角色:
- 抽象主題(Subject)類:通過接口或抽象類聲明真實主題和代理對象實現的業務方法。
- 真實主題(Real Subject)類:實現了抽象主題中的具體業務,是代理對象所代表的真實對象,是最終要引用的對象。
- 代理(Proxy)類:提供了與真實主題相同的接口,其內部含有對真實主題的引用,它可以訪問、控制或擴展真實主題的功能。
實例
第一步:首先存在一個抽象主題接口
Interface Subject{public function request(); }第二步:存在一個真實主題
class RealSubject implements Subject{public function request(){echo "這個是真實主題\n";} }第三步:使用一個代理模式
class Proxy implements Subject{public $realSubject;public function __construct(){$this->realSubject = new RealSubject(); }public function request(){$this->preRequest();$this->realSubject->request();$this->postRequest();}public function preRequest(){echo "這是調用真實主題之前的\n";}public function postRequest(){echo "這是調用真實主題之后的\n";} }第四步:測試
$testProxy = new Proxy(); $testProxy->request();d模式的應用場景
- 遠程代理,這種方式通常是為了隱藏目標對象存在于不同地址空間的事實,方便客戶端訪問。例如,用戶申請某些網盤空間時,會在用戶的文件系統中建立一個虛擬的硬盤,用戶訪問虛擬硬盤時實際訪問的是網盤空間。
- 虛擬代理,這種方式通常用于要創建的目標對象開銷很大時。例如,下載一幅很大的圖像需要很長時間,因某種計算比較復雜而短時間無法完成,這時可以先用小比例的虛擬代理替換真實的對象,消除用戶對服務器慢的感覺。
- 安全代理,這種方式通常用于控制不同種類客戶對真實對象的訪問權限。
- 智能指引,主要用于調用目標對象時,代理附加一些額外的處理功能。例如,增加計算真實對象的引用次數的功能,這樣當該對象沒有被引用時,就可以自動釋放它。
- 延遲加載,指為了提高系統的性能,延遲對目標的加載。例如,Hibernate 中就存在屬性的延遲加載和關聯表的延時加載。
3. 橋梁模式(Bridge)
引用設計模式(八)橋梁模式(Bridge),這篇文章中的一個例子:
現需要提供大中小3種型號的畫筆,能夠繪制5種不同顏色,如果使用蠟筆,我們需要準備3*5=15支蠟筆,也就是說必須準備15個具體的蠟筆類。而如果使用毛筆的話,只需要3種型號的毛筆,外加5個顏料盒,用3+5=8個類就可以實現15支蠟筆的功能。實際上,蠟筆和毛筆的關鍵一個區別就在于筆和顏色是否能夠分離。
為什么需要Bridge模式?
一個類中有多個緯度的變化,那可以使用Bridge模式對該類進行解耦,即將多個緯度進行抽象。所以橋梁模式的用意是“將抽象化與實現化脫耦,使得二者可以獨立地變化。”
什么是Bridge模式?
橋接(Bridge)模式包含以下主要角色。
- 抽象化(Abstraction)角色:定義抽象類,并包含一個對實現化對象的引用。
- 擴展抽象化(Refined Abstraction)角色:是抽象化角色的子類,實現父類中的業務方法,并通過組合關系調用實現化角色中的業務方法。
- 實現化(Implementor)角色:定義實現化角色的接口,供擴展抽象化角色調用。
- 具體實現化(Concrete Implementor)角色:給出實現化角色接口的具體實現。
實例
可以實現一個包含顏色的形狀接口。
第一步:定義一個顏色接口(Implementor角色)。定義一個形狀抽象類(Abstraction角色),其中包含一個顏色接口的引用。
//定義顏色接口 Interface Color{public function showColor(); }//形狀抽象類 abstract class Shape {protected $color;public function __construct(Color $color){$this->color = $color;}public function setColor(Color $color){$this->color = $color;}abstract public function draw(); }第二步:實現具體化實現角色(Concrete Implementor)
class Red implements Color{public function showColor(){return "red";} }class Green implements Color{public function showColor(){return "green";} }第三步:實現擴展抽象化(Refined Abstraction)角色
class Square extends Shape{public function draw(){echo "i am " . $this->color->showColor() . " square\n";} }第四步:測試
$redSquare = new Square(new Red()); $redSquare->draw(); $greenSquare = new Square(new Green()); $greenSquare->draw();4.裝飾模式(Decorator)
在現實生活中,常常需要對現有產品增加新的功能或美化其外觀,如房子裝修、相片加相框等。
為什么需要裝飾模式?
在軟件開發過程中,有時想用一些現存的組件。這些組件可能只是完成了一些核心功能。但在不改變其結構的情況下,可以動態地擴展其功能。所有這些都可以釆用裝飾模式來實現。
什么是裝飾模式?
裝飾(Decorator)模式的定義:指在不改變現有對象結構的情況下,動態地給該對象增加一些職責(即增加其額外功能)的模式,它屬于對象結構型模式。
裝飾模式主要包含以下角色。
- 抽象構件(Component)角色:定義一個抽象接口以規范準備接收附加責任的對象。
- 具體構件(Concrete Component)角色:實現抽象構件,通過裝飾角色為其添加一些職責。
- 抽象裝飾(Decorator)角色:繼承抽象構件,并包含具體構件的實例,可以通過其子類擴展具體構件的功能。
- 具體裝飾(ConcreteDecorator)角色:實現抽象裝飾的相關方法,并給具體構件對象添加附加的責任。
實例
比如現在有一個輸出字符串接口,現在只能輸出原有字符串,現在想要增加輸出JSON,XML等字符串的功能。
第一步:先定義系統中已經存在的構件
Interface Component{public function renderData(); }class ConcreteComponent implements Component{public $data; public function __construct($data){$this->data = $data;}//輸出字符串功能public function renderData(){return $this->data; } }第二步:定義一個抽象裝飾角色
abstract class Decorator implements Component {protected $component;public function __construct(Component $component){$this->component = $component;} }第三步:定義具體的裝飾類
// Json裝飾類 class JsonComponent extends Decorator{public function renderData(){return json_encode($this->component->renderData());} }// XML裝飾類 class XmlComponent extends Decorator{public function renderData(){return "this is Xml renderData method";} }第四步:測試
$component = new ConcreteComponent(["1", "2"]); var_dump($component->renderData());$jsonComponent = new JsonComponent($component); var_dump($jsonComponent->renderData());$xmlComponent = new XmlComponent($component); var_dump($xmlComponent->renderData());轉載于:https://www.cnblogs.com/qiye5757/p/10013048.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的敏捷软件开发学习笔记(四)之结构型设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 分布式自增ID算法---雪花算法(Sno
- 下一篇: 【nodejs】让nodejs像后端mv