天天看點

設計模式 - 擴充卡模式簡介PHP 代碼示例

簡介

場景

  • 現實場景:國内電壓是 220v,外國部分國家是 110v,如果去出差,會需要攜帶兩個電源擴充卡,以應對這兩種不同的電壓。
  • 資料庫場景:每種程式設計語言都需要支援多種資料庫,通常會抽象一層資料庫連接配接層,例如 Java 的 JDBC,PHP 的 PDO。資料庫連接配接層對應用開發人員提供标準接口,屏蔽了資料庫底層的差異。資料庫提供的接口則是千差萬别的。是以,資料庫連接配接層又拆分為兩層,一層對外提供服務,一層用于連接配接不同的資料庫。
  • 具體代碼場景:想使用一個已經完成的類,但是它的接口不符合需求。

假設已經有可以提供服務的目标類,客戶類通路目标類時,發現其提供的接口不滿足需求。此時在客戶類和目标類中間加一層抽象,使不能直接互動的類可以一起工作。

定義一個包裝類,包裝不相容接口的對象,這個包裝類指的就是擴充卡(Adapter),它所包裝的對象就是适配者(Adaptee),即被适配的類。

模式定義

将一個接口轉換成客戶希望的另一個接口,使接口不相容的那些類可以一起工作。

模式特點

擴充卡模式包含四個角色:

Target:目标抽象類,定義接口标準,用戶端可以直接調用

Adapter:擴充卡類,适配 Adaptee 與 Target,使其可以協同工作

Adaptee:适配者類,需要進行适配的接口

Client:客戶類

擴充卡模式包括兩種:

  • 類結構型擴充卡:繼承關系,Adapter 同時繼承 Target 和 Adaptee 類。
  • 對象結構型擴充卡:關聯關系,Adapter 繼承 Target,關聯 Adaptee。
設計模式 - 擴充卡模式簡介PHP 代碼示例
設計模式 - 擴充卡模式簡介PHP 代碼示例

優點

  • 符合“開閉原則”,可以用配置檔案友善地更換擴充卡
  • 解耦,通過引入一個擴充卡類來重用現有的适配者類

類擴充卡模式優點:

  • Adapter 是 Adaptee 的子類,是以可以在 Adapter 中置換一些 Adaptee 的方法,使得擴充卡的靈活性更強。

對象擴充卡模式優點:

  • 允許一個 Adapter 與多個 Adaptee 同時工作

缺點

類擴充卡模式的缺點:

  • 對于不支援多繼承的語言,一次最多隻能适配一個 Adaptee,其使用有一定的局限性,不能将 Adaptee 和它的子類都适配到目标接口。當我們想要比對一個類以及所有它的子類時,類 Adapter 不能勝任工作。

對象擴充卡模式的缺點:

  • 重定義 Adaptee 的行為比較困難。

PHP 代碼示例

類擴充卡模式

<?php

interface Target {
    public function query();
}

class Adapter extends Adaptee implements Target {
    public function del() {
        echo "can not delete<br/>";
    }
}

class Adaptee {
    public function query() {
        echo "Adaptee query<br/>";
    }
}

class Client {
    public function test() {
        $adapter = new Adapter();

        $adapter->query();
        $adapter->del();
    }
}

$c = new Client();
$c->test();
           

輸出:

Adaptee query
can not delete
           

對象擴充卡模式

<?php

interface Target {
    public function query();
}

class Adapter implements Target {
    private $adaptee;

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

    public function query() {
        echo $this->adaptee->query();
    }

    public function del() {
        echo "can not delete<br/>";
    }
}

class Adaptee {
    public function query() {
        echo "Adaptee query<br/>";
    }
}

class Client {
    public function test() {
        $adaptee = new Adaptee();
        $adapter = new Adapter($adaptee);

        $adapter->query();
        $adapter->del();
    }
}

$c = new Client();
$c->test();
           

輸出:

Adaptee query
can not delete
           

繼續閱讀