適配器模式和php實現

来源:http://www.cnblogs.com/yujon/archive/2016/05/27/5534759.html
-Advertisement-
Play Games

1. 概述 將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。 2. 解決的問題 即Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。 3. 模式中的角色 3.1 目標介面(Target):客戶所期待 ...


1. 概述

  將一個類的介面轉換成客戶希望的另外一個介面。Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。

2. 解決的問題

  即Adapter模式使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。

3. 模式中的角色

  3.1 目標介面(Target):客戶所期待的介面。目標可以是具體的或抽象的類,也可以是介面。

  3.2 源介面/類(Adaptee):需要適配的類或適配者類。

  3.3 適配器(Adapter):通過包裝一個需要適配的對象,把源介面轉換成目標介面。  

4. UML圖:

  ../_images/Adapter.jpg

5 代碼實現:

<?php
header("Content-type:text/html;Charset=utf-8");
//目標對象
interface Target{
    function mothed();
}

//源介面
interface Adaptee{
    function mothed();
}
class ConcreteAdaptee implements Adaptee{
    function mothed(){
        echo "源方法";
    }
}


//適配器
class Adapter Implements Target{
    private $adaptee;
    function  __construct(Adaptee $adaptee){
         $this->adaptee = $adaptee;
    }
    //override目標介面的方法執行的卻是源介面的方法從實現適配
    function mothed(){
        $this->adaptee->mothed();
    }
}

//測試
$adaptee = new ConcreteAdaptee();
$adapter = new Adapter($adaptee);
$adapter->mothed();
?>

 

6:具體實例:

<?php
// 代碼中有兩個介面,分別為德標介面和國標介面,分別命名為DBSocketInterface和GBSocketInterface,此外還有兩個實現類,分別為德國插座和中國插座,
分別為DBSocket和GBSocket。為了提供兩套介面之間的適配,我們提供了一個適配器,叫做SocketAdapter。除此之外,還有一個客戶端,比如是我們去德國旅游
時住的一家賓館,叫Hotel,在這個德國旅館中使用德國介面。 // 德標介面:
interface DBSocketInterface{ /** * 這個方法的名字叫做:使用兩項圓頭的插口供電 * 本人英語就這個水平 */ function powerWithTwoRound(); } // 德國插座實現德標介面 class DBSocket implements DBSocketInterface{ public function powerWithTwoRound(){ echo "使用兩項圓頭的插孔供電"; } } // 德國旅館是一個客戶端,它裡面有德標的介面,可以使用這個德標介面給手機充電: class Hotel{ //旅館中有一個德標的插口 private $dbSocket; public function Hotel(DBSocketInterface $dbSocket) { $this->dbSocket = $dbSocket; } public function setSocket (DBSocketInterface $dbSocket){ $this->dbSocket = $dbSocket; } //旅館中有一個充電的功能 public function charge(){ //使用德標插口充電 $this->dbSocket->powerWithTwoRound(); } } // 現在寫一段代碼進行測試: class Test { public static function main() { //初始化一個德國插座對象, 用一個德標介面引用它 $dbSoket = new DBSocket(); //創建一個旅館對象 $hotel = new Hotel($dbSoket); //在旅館中給手機充電 $hotel->charge(); } } // 運行程式,列印出以下結果: 使用兩項圓頭的插孔供電 // 現在我去德國旅游,帶去的三項扁頭的手機充電器。如果沒有帶電源適配器,我是不能充電的,因為不可能為了我一個旅客而為我更改牆上的插座,
更不可能為我專門蓋一座使用中國國標插座的賓館。因為人家德國人一直這麼使用,並且用的挺好,俗話說入鄉隨俗,我就要自己想辦法來解決問題。
對應到我們的代碼中,也就是說,上面的Hotel類,DBSocket類,DBSocketInterface介面都是不可變的(由德國的客戶提供),如果我想使用這一套API,那麼只能自己寫代碼解決。 // 下麵是國標介面和中國插座的代碼。 // 國標介面:
interface GBSocketInterface { /** * 這個方法的名字叫做:使用三項扁頭的插口供電 * */ function powerWithThreeFlat(); } // 中國插座實現國標介面: class GBSocket implements GBSocketInterface{ public function powerWithThreeFlat() { echo "使用三項扁頭插孔供電"; } } // 可以認為這兩個東西是我帶到德國去的,目前他們還不能使用,因為介面不一樣。那麼我必須創建一個適配器,這個適配器必須滿足以下條件: // 1 必須符合德國標準的介面,否則的話還是沒辦法插到德國插座中; 2 在調用上面實現的德標介面進行充電時,提供一種機制,將這個調用轉到對國標介面的調用 。 // 這就要求: 1 適配器必須實現原有的舊的介面 2 適配器對象中持有對新介面的引用,當調用舊介面時,將這個調用委托給實現新介面的對象來處理,也就是在適配器對象中組合一個新介面。 // 下麵給出適配器類的實現: class SocketAdapter implements DBSocketInterface{ //實現舊介面 //組合新介面 private $gbSocket; /** * 在創建適配器對象時,必須傳入一個新街口的實現類 * */ public function SocketAdapter(GBSocketInterface $gbSocket) { $this->gbSocket = $gbSocket; } /** * 將對就介面的調用適配到新介面 */ public function powerWithTwoRound() { $this->gbSocket->powerWithThreeFlat(); } } // 這個適配器類滿足了上面的兩個要求。下麵寫一段測試代碼來驗證一下適配器能不能工作,我們按步驟一步步的寫出代碼,以清楚的說明適配器是如何使用的。 // 1 我去德國旅游,帶去的充電器是國標的(可以將這裡的GBSocket看成是充電器) $gbSocket = new GBSocket(); // 2 來到德國後, 找到一家德國賓館住下 (這個賓館還是上面代碼中的賓館,使用的依然是德國標準的插口) $hotel = new Hotel(); // 3 由於沒法充電,我拿出隨身帶去的適配器,並且將我帶來的充電器插在適配器的上端插孔中。這個上端插孔是符合國標的,我的充電器完全可以插進去。 $socketAdapter = new SocketAdapter($gbSocket); // 4 再將適配器的下端插入賓館里的插座上 $hotel->setSocket($socketAdapter); // 5 可以在賓館中使用適配器進行充電了 $hotel->charge(); // 上面的五個步驟就是適配器的使用過程,下麵是完整的測試代碼。 class TestAdapter { public static function main() { $gbSocket = new GBSocket(); $hotel = new Hotel(); $socketAdapter = new SocketAdapter($gbSocket); $hotel->setSocket($socketAdapter); $hotel->charge(); } } ?>

 

7 優點

  7.1 通過適配器,客戶端可以調用同一介面,因而對客戶端來說是透明的。這樣做更簡單、更直接、更緊湊。

  7.2 復用了現存的類,解決了現存類和復用環境要求不一致的問題。

  7.3 將目標類和適配者類解耦,通過引入一個適配器類重用現有的適配者類,而無需修改原有代碼。

  7.4 一個對象適配器可以把多個不同的適配者類適配到同一個目標,也就是說,同一個適配器可以把適配者類和它的子類都適配到目標介面。

8 缺點

  對於對象適配器來說,更換適配器的實現過程比較複雜。

9適用場景

  9.1系統需要使用現有的類,而這些類的介面不符合系統的介面。

  9.2想要建立一個可以重用的類,用於與一些彼此之間沒有太大關聯的一些類,包括一些可能在將來引進的類一起工作。

  9.3 兩個類所做的事情相同或相似,但是具有不同介面的時候。

 9.4 舊的系統開發的類已經實現了一些功能,但是客戶端卻只能以另外介面的形式訪問,但我們不希望手動更改原有類的時候。

 9.5 使用第三方組件,組件介面定義和自己定義的不同,不希望修改自己的介面,但是要使用第三方組件介面的功能。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.意圖 將對象組合成樹形結構以表示“部分-整體”的層次結構。Composite使得用戶對單個對象和組合對象的使用具有一致性。 2.動機 可以組合多個簡單組件以形成一些較大的組件,這些組件又可以組合成更大的組件。Composite模式描述瞭如何使用遞歸組合,使得用戶不必對這些類進行區別。 3.適用性 ...
  • 中介者模式: 中介者模式(Mediator Pattern)定義:用一個中介對象來封裝一系列的對象交互,中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。中介者模式又稱為調停者模式,它是一種對象行為型模式。 模式動機: 1.在用戶與用戶直接聊天的設計方案中,用戶 ...
  • 解釋器模式: 給定一個語言, 定義它的文法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。 角色: 環境角色:定義解釋規則的全局信息。 抽象解釋器::定義了部分解釋具體實現,封裝了一些由具體解釋器實現的介面。 具體解釋器(MusicNote):實現抽象解釋器的介面,進行具體的解釋 ...
  • 1.意圖 將抽象部分與它的實現部分分離,使它們都可以獨立地變化。 2.動機 在抽象類與它的實現之間起到橋梁作用,使它們可以獨立地變化。 3.適用性 不希望在抽象和它的實現部分之間有一個固定的綁定關係。這種情況可能是因為,在程式運行時刻實現部分可以被選擇或切換。 類的抽象以及它的實現部分都應該可以通過 ...
  • 今天看到一篇講解設計模式六大原則的文章,非常深刻細緻,轉過來給大家共同學習。 作者:zhengzhb ,發佈於2012-11-2,來源:CSDN 作者:zhengzhb ,發佈於2012-11-2,來源:CSDN 設計模式六大原則(1):單一職責原則 定義:不要存在多於一個導致類變更的原因。通俗的說 ...
  • 代理模式和裝飾模式有很大的相似性,二者的類圖(幾乎)是一樣的。下麵分別講解代理模式和裝飾模式。 1、代理模式 一般著名的跑步運動員都會有自己的代理人,如果想聯繫該運動員的比賽事宜,可以直接聯繫他的代理人就可以了。類圖如下所示: IRunner介面如下: Runner類如下所示: RunnerAgen ...
  • 外觀模式: 外觀模式(Facade Pattern):外部與一個子系統的通信必須通過一個統一的外觀對象進行,為子系統中的一組介面提供一個一致的界面,外觀模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。外觀模式又稱為門面模式,它是一種對象結構型模式。 目的: 1、為一個複雜子系統提供簡單的 ...
  • 裝飾模式(Decorator Pattern) : 動態地給一個對象增加一些額外的職責(Responsibility),就增加對象功能來說,裝飾模式比生成子類實現更為靈活。其別名也可以稱為包裝器(Wrapper),與適配器模式的別名相同,但它們適用於不同的場合。根據翻譯的不同,裝飾模式也有人稱之為“ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...