PHP設計模式之適配器模式

PHP設計模式之適配器模式

這個模式一直以來都有一個很經典的例子,那就是插座!沒錯,當咱們從國外買回來電器,或者旅遊出差去國外的時候,常常會須要一個電源適配器,由於我國的電壓標準是220伏,而其餘國家則有110伏的標準。而這個電源適配器正是適配器模式的一種標誌。當對象不太符合要求的時候,給他加一個適配器唄!!php

Gof類圖及解釋

GoF定義:將一個類的接口轉換成客戶但願的另一個接口。Adapter模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做git

GoF類圖github

繼承式編程

適配器方法結構類圖-繼承式

組合式設計模式

適配器方法結構類圖-組合式

代碼實現安全

interface Target{
    function Request() : void;
}
複製代碼

定義一個接口契約,也能夠是一個正常的有實現方法的類(後面的例子咱們會用類)this

class Adapter implements Target{
    private $adaptee;

    function __constuct($adaptee){
        $this->adaptee = $adaptee;
    }

    function Request() : void {
        $this->adaptee->SpecificRequest();
    }
}
複製代碼

適配器實現這個接口契約,讓Request()方法得以實現,但請注意,咱們真正調用的實際上是Adaptee類中的方法阿里雲

class Adaptee {
    function SpecificRequest() : void{
        echo "I'm China Standard!";
    }
}
複製代碼
  • 適配器有兩種形式,上方類圖中給出了,咱們代碼實現的組合形式的
  • 繼承形式的在GoF書中是以C++爲示例的,由於C++能夠實現多重繼承,但如今流行的大部分語言是以接口爲形式的,也能夠實現,但使用這種形式的適配器很少
  • 其實仍是面向接口編程的一種思惟,相似於裝飾器對舊功能的包裝,咱們這裏就是直接去進行了替換,但對外的調用仍是保持不變
  • 適配器模式其實很好理解,代碼真的就只有這麼點

又說到個人手機工廠了,這回我們的生意真的作大了哦!賣到泰國、新加坡、印度尼西亞去了,反正有咖喱的地方都有咱們的身影了。聽說是咱們出了個咖喱色。換殼這事兒可不徹底是由於受到諾X亞的影響,而是真的通過長期的調研咱們發現不一樣顏色在不一樣的地方銷量會更好。因而,富X康在原有的手機殼生產線(Target)上爲咱們加裝了一個噴塗適配器(adapter),當咱們須要其餘顏色的殼時,只須要這個適配器換不一樣的顏料就好啦(adaptee),直接裝上這個噴塗器,新的顏色的手機就誕生了。而當向另一個國家擴展業務時,咱們換顏料就行啦,用過久了不行就連噴頭也換掉(是否是想起了連供打印機)spa

完整代碼:適配器模式設計

實例

繼續發短信,看我能編到何時~~~

各位大拿在對接信息、支付類的接口時,常常會使用這些平臺提供的SDK。特別是有了Composer以後,安裝SDK就更加的方便了,可是,又有一個嚴重的問題,這幫人作的SDK雖然說功能實現大同小異,但命名但是千差萬別啊!!咱們的系統原來一直使用的阿里雲的業務,可是這回要增長極光和百度雲的信息功能,一來作個後備,二來根據不一樣業務使用不一樣的接口達到安全或節約的目的,有沒有辦法統一一下他們對外的接口,讓咱們使用他們的SDK時可以很是方便的和以前使用你們都已經很習慣的阿里雲的接口同樣呢?固然有,給他們各自都上個適配器唄,實例化的時候大不了外面再套個工廠返回不一樣的適配器就好啦,只要適配器裏的實現方法和阿里雲同樣就OK啦!

短信發送類圖

短信發送裝飾器方法

完整源碼:短信發送適配器方法

<?php

class Message{
    public function send(){
        echo "阿里雲發送短信!" . PHP_EOL;
    }
    public function push(){
        echo "阿里雲發送推送!" . PHP_EOL;
    }
}

class JiguangSDKAdapter extends Message{
    private $message;

    public function __construct($message){
        $this->message = $message;
    }

    public function send(){
        $this->message->send_out_msg();
    }
    public function push(){
        $this->message->push_msg();
    }
}

class JiguangMessage{
    public function send_out_msg(){
        echo "極光發送短信!" . PHP_EOL;
    }
    public function push_msg(){
        echo "極光發送推送!" . PHP_EOL;
    }
}
class BaiduYunSDKAdapter extends Message{
    private $message;

    public function __construct($message){
        $this->message = $message;
    }

    public function send(){
        $this->message->transmission_msg();
    }
    public function push(){
        $this->message->transmission_push();
    }
}
class BaiduYunMessage{
    public function transmission_msg(){
        echo "百度雲發送短信!" . PHP_EOL;
    }
    public function transmission_push(){
        echo "百度雲發送推送!" . PHP_EOL;
    }
}

$jiguangMessage = new JiguangMessage();
$baiduYunMessage = new BaiduYunMessage();
$message = new Message();

// 原來的老系統發短信,使用阿里雲
$message->send();
$message->push();


// 部分模塊用極光發吧
$jgAdatper = new JiguangSDKAdapter($jiguangMessage);
$jgAdatper->send();
$jgAdatper->push();

// 部分模塊用百度雲發吧
$bdAatper = new BaiduYunSDKAdapter($baiduYunMessage);
$bdAatper->send();
$bdAatper->push();
複製代碼

說明

  • 在這個例子中,咱們有兩個適配器,由於有兩個SDK須要咱們去適配,誰說只能有一個電源轉換器,萬一哪一個神奇的國度是用500伏的電壓呢,因此仍是多帶個電源轉換器吧
  • 這裏咱們是繼承的Message類,由於Message類是以前已經寫好的代碼,裏面可能有一些能夠公用的方法,因此並無作接口抽象。能夠考慮在重構代碼的時候實現提取一個抽象接口,但在這裏只是爲了演示適配器不必定只是能去針對接口,只要和原對象保持一致,不去繼承什麼也是能夠的,畢竟咱們是弱類型語言,若是是相似於Java的強類型,那麼繼承或者實現仍是頗有必要的(多態性)
  • 組合式的適配器與裝飾器相似,都會維護一個外部對象,裝飾器更多的會使用原來的類中的方法,對其進行增長功能的操做,而適配器則不多去增長功能,而是直接替換掉
  • Laravel中的Filesystem模塊,有一個FilesystemAdapter類,我以爲沒啥可說的了,很明顯的告訴你們咱用了適配器模式,好好研究一下吧
  • 當你想使用一個類,但他提供的內容跟你的業務又不太匹配的時候;或者你想建立一個類,能夠與其餘不相關的類或不可預見的類協同工做的時候,不妨試試適配器模式吧

下期看點

事件訂閱有沒有據說過?沒有?若是地震算一個事件的話,那麼一旦發生這個災難了,立刻會有種類政府部門和社會團隊開始行動,救援、搶險等各類工做立刻展開,咱們能夠把整個社會力量都當作是訂閱者,包括咱們每個都會很關心災區的狀況。在這裏,咱們全部人都是觀察者。這下就很容易理解觀察者模式了吧,下節咱們再詳述!

相關文章
相關標籤/搜索