目錄
主要角色
適用性
什麼時候使用適配器模式呢? " >什麼時候使用適配器模式呢?
一開始的和諧
更加煩躁
首頁 後端開發 php教程 關於php設計模式-適配器的方法詳解

關於php設計模式-適配器的方法詳解

Mar 17, 2018 pm 03:58 PM
php 設計模式 適配器

將一個類別的接口轉換成客戶希望的另外一個接口,Adapter模式使得原來由於接口不相容而不能一起工作的那此類可以一起工作。本文主要和大家分享適配器的詳解,希望能幫助大家。

主要角色

目標角色:定義客戶端使用的與特定領域相關的接口,這就是我們所期待的

#來源角色:需要進行適配的介面

適配器角色:對Adaptee的介面與target介面進行適配器是本模式的核心,適配器將來源介面轉成目標接口,此角色為具體的類別

適用性

1、你想使用一個已經存在的類,而它的介面不符合你的需求

2、你想創建一個可以復用的類,該類可以與其他不相關的類或不可預見的類協同工作

3、你想要一個已經存在的子類,但是不可能對每一個都進行子類化以匹配它們的接口。物件適配器可以適應它的父類別介面(僅限於物件適配器)

//目标角色  
interface Target {  
    public function simpleMethod1();  
    public function simpleMethod2();  
}  
  
//源角色  
class Adaptee {  
      
    public function simpleMethod1(){  
        echo &#39;Adapter simpleMethod1&#39;."<br>";  
    }  
}  
  
//类适配器角色  
class Adapter implements Target {  
    private $adaptee;  
      
      
    function __construct(Adaptee $adaptee) {  
        $this->adaptee = $adaptee;   
    }  
      
    //委派调用Adaptee的sampleMethod1方法  
    public function simpleMethod1(){  
        echo $this->adaptee->simpleMethod1();  
    }  
      
    public function simpleMethod2(){  
        echo &#39;Adapter simpleMethod2&#39;."<br>";     
    }   
      
}  
  
//客户端  
class Client {  
      
    public static function main() {  
        $adaptee = new Adaptee();  
        $adapter = new Adapter($adaptee);  
        $adapter->simpleMethod1();  
        $adapter->simpleMethod2();   
    }  
}  
  
Client::main();
登入後複製

也許上述這麼講,你們還不知道什麼是適配器。那接下來,我再詳細的講解一下

什麼時候使用適配器模式呢?

其實最簡單的一個例子就是使用第三方類別庫。這些類別庫都會隨著版本的升級,對應的api也會改變。當介面改變的時候,適配器就派上用場了

我舉一個實際的例子吧

一開始的和諧

#黑棗玩具公司專門生產玩具,生產的玩具不限於狗、貓、獅子,魚等動物。每個玩具都可以進行「張嘴」與「閉嘴」操作,分別呼叫了openMouth與closeMouth方法。 在這個時候,我們很容易想到可以第一定義一個抽象類別Toy,甚至是介面Toy,這些問題不大,其他的類別去繼承父類,實作父類別的方法。一片和諧,信心向榮。

平滑的破壞

為了擴大業務,現在黑棗玩具公司與紅棗遙控公司合作,紅棗遙控公司可以使用遙控設備對動物進行嘴巴控制。不過紅棗遙控公司的遙控設備是呼叫的動物的doMouthOpen及doMouthClose方法。黑棗玩具公司的程式設計師現在必須要做的是對Toy系列類別進行升級改造,使Toy能呼叫doMouthOpen及doMouthClose方法。

 考慮實現的方法時,我們很直接地想到,你需要的話我再在我的父類子類裡給你添加這麼兩個方法就好啦。當你一次又一次在父類別子類別裡面重複加入這兩個方法的時候,總會想著如此重複的工作,難道不能解決麼?當有數百個子類別的時候,程式設計師會改瘋的。程式設計師往往比的是誰在不影響效率的時候更會「偷懶」。這樣做下去程式設計師會覺得自己很傻。 (其實我常常當這樣的傻子)

abstract class Toy
{
    public abstract function openMouth();

    public abstract function closeMouth();

    //为红枣遥控公司控制接口增加doMouthOpen方法
    public abstract function doMouthOpen();

    //为红枣遥控公司控制接口增加doMouthClose方法
    public abstract function doMouthClose();
}

class Dog extends Toy
{
    public function openMouth()
    {
        echo "Dog open Mouth\n";
    }

    public function closeMouth()
    {
        echo "Dog open Mouth\n";
    }

    //增加的方法
    public function doMouthOpen()
    {
        $this->doMouthOpen();
    }

    //增加的方法
    public function doMouthClose()
    {
        $this->closeMouth();
    }
}

class Cat extends Toy
{
    public function openMouth()
    {
        echo "Cat open Mouth\n";
    }

    public function closeMouth()
    {
        echo "Cat open Mouth\n";
    }

    //增加的方法
    public function doMouthOpen()
    {
        $this->doMouthOpen();
    }

    //增加的方法
    public function doMouthClose()
    {
        $this->closeMouth();
    }
}
登入後複製

更加煩躁

程式設計師剛剛碼完程式碼,喝了口水,突然間另一個訊息傳來。 黑棗玩具公司也要與綠棗遙控公司合作,因為綠棗遙控公司遙控設備較便宜且穩定。不過綠棗遙控公司的遙控設備是呼叫的動物的operMouth(type)方法來實現嘴巴控制。若type為0則“閉嘴”,反之張嘴。 這下好了,程式設計師又得對Toy及其子類別進行升級,使Toy能呼叫operMouth()方法。擱誰都不淡定了。

abstract class Toy  
{  
    public abstract function openMouth();  
  
    public abstract function closeMouth();  
  
    public abstract function doMouthOpen();  
  
    public abstract function doMouthClose();  
  
    //为绿枣遥控公司控制接口增加doMouthClose方法  
    public abstract function operateMouth($type = 0);  
}  
  
class Dog extends Toy  
{  
    public function openMouth()  
    {  
        echo "Dog open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Dog open Mouth\n";  
    }  
  
    public function doMouthOpen()  
    {  
        $this->doMouthOpen();  
    }  
  
    public function doMouthClose()  
    {  
        $this->closeMouth();  
    }  
  
    public function operateMouth($type = 0)  
    {  
        if ($type == 0) {  
            $this->closeMouth();  
        } else {  
            $this->operateMouth();  
        }  
    }  
}  
  
class Cat extends Toy  
{  
    public function openMouth()  
    {  
        echo "Cat open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Cat open Mouth\n";  
    }  
  
    public function doMouthOpen()  
    {  
        $this->doMouthOpen();  
    }  
  
    public function doMouthClose()  
    {  
        $this->closeMouth();  
    }  
  
    public function operateMouth($type = 0)  
    {  
        if ($type == 0) {  
            $this->closeMouth();  
        } else {  
            $this->operateMouth();  
        }  
    }  
}
登入後複製

在這個時候,程式設計師必須要動腦子想辦法了,就算自己勤快,萬一哪天紫棗青棗黃棗山棗這些遙控公司全來的時候,忽略自己不斷增多的工作量不說,這個Toy類別可是越來越大,總有一天程式設計師不崩潰,系統也會崩潰。

問題出在哪裡呢

像上面那樣寫程式碼,程式碼實作違反了「開-閉」原則,一個軟體實體應當對擴充開放,對修改關閉。即在設計一個模組的時候,應當使這個模組可以在不被修改的前提下被擴展。也就是說每個屍體都是一個小王國,你讓我參與你的事情這個可以,但你不能修改我的內部,除非我的內部程式碼確實可以優化。 

在這個想法下,我們懂得如何去用繼承,如何利用多型,甚至如何實現「高內聚,低耦合」。

回到这个问题,我们现在面临这么一个问题,新的接口方法我要实现,旧的接口(Toy抽象类)也不能动,那么总得有个解决方法吧。那就是引入一个新的类--我们本文的主角--适配器。 适配器要完成的功能很明确,引用现有接口的方法实现新的接口的方法。更像它名字描述的那样,你的接口不改的话,我就利用现有接口和你对接一下吧。

到此,解决方法已经呼之欲出了,下面贴上代码。

<?php
abstract class Toy  
{  
    public abstract function openMouth();  
  
    public abstract function closeMouth();  
}  
  
class Dog extends Toy  
{  
    public function openMouth()  
    {  
        echo "Dog open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Dog close Mouth\n";  
    }  
}  
  
class Cat extends Toy  
{  
    public function openMouth()  
    {  
        echo "Cat open Mouth\n";  
    }  
  
    public function closeMouth()  
    {  
        echo "Cat close Mouth\n";  
    }  
}


//目标角色:红枣遥控公司  
interface RedTarget  
{  
    public function doMouthOpen();  
  
    public function doMouthClose();  
}  
  
//目标角色:绿枣遥控公司及  
interface GreenTarget  
{  
    public function operateMouth($type = 0);  
}


//类适配器角色:红枣遥控公司  
class RedAdapter implements RedTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee的sampleMethod1方法  
    public function doMouthOpen()  
    {  
        $this->adaptee->openMouth();  
    }  
  
    public function doMouthClose()  
    {  
        $this->adaptee->closeMouth();  
    }  
}  
  
//类适配器角色:绿枣遥控公司  
class GreenAdapter implements GreenTarget  
{  
    private $adaptee;  
  
    function __construct(Toy $adaptee)  
    {  
        $this->adaptee = $adaptee;  
    }  
  
    //委派调用Adaptee:GreenTarget的operateMouth方法  
    public function operateMouth($type = 0)  
    {  
        if ($type) {  
            $this->adaptee->openMouth();  
        } else {  
            $this->adaptee->closeMouth();  
        }  
    }  
}



class testDriver  
{  
    public function run()  
    {  
         //实例化一只狗玩具  
        $adaptee_dog = new Dog();  
        echo "给狗套上红枣适配器\n";  
        $adapter_red = new RedAdapter($adaptee_dog);  
        //张嘴  
        $adapter_red->doMouthOpen();  
        //闭嘴  
        $adapter_red->doMouthClose();  
        echo "给狗套上绿枣适配器\n";  
        $adapter_green = new GreenAdapter($adaptee_dog);  
        //张嘴  
        $adapter_green->operateMouth(1);  
        //闭嘴  
        $adapter_green->operateMouth(0);  
    }  
}  
  
$test = new testDriver();  
$test->run();
登入後複製

更加烦躁
最后的结果就是,Toy类及其子类在不改变自身的情况下,通过适配器实现了不同的接口。

最后的总结

将一个类的接口转换成客户希望的另外一个接口,使用原本不兼容的而不能在一起工作的那些类可以在一起工作.

适配器模式核心思想:把对某些相似的类的操作转化为一个统一的“接口”(这里是比喻的说话)--适配器,或者比喻为一个“界面”,统一或屏蔽了那些类的细节。适配器模式还构造了一种“机制”,使“适配”的类可以很容易的增减,而不用修改与适配器交互的代码,符合“减少代码间耦合”的设计原则。

以上是關於php設計模式-適配器的方法詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles