簡介
場景
- 現實場景:國内電壓是 220v,外國部分國家是 110v,如果去出差,會需要攜帶兩個電源擴充卡,以應對這兩種不同的電壓。
- 資料庫場景:每種程式設計語言都需要支援多種資料庫,通常會抽象一層資料庫連接配接層,例如 Java 的 JDBC,PHP 的 PDO。資料庫連接配接層對應用開發人員提供标準接口,屏蔽了資料庫底層的差異。資料庫提供的接口則是千差萬别的。是以,資料庫連接配接層又拆分為兩層,一層對外提供服務,一層用于連接配接不同的資料庫。
- 具體代碼場景:想使用一個已經完成的類,但是它的接口不符合需求。
假設已經有可以提供服務的目标類,客戶類通路目标類時,發現其提供的接口不滿足需求。此時在客戶類和目标類中間加一層抽象,使不能直接互動的類可以一起工作。
定義一個包裝類,包裝不相容接口的對象,這個包裝類指的就是擴充卡(Adapter),它所包裝的對象就是适配者(Adaptee),即被适配的類。
模式定義
将一個接口轉換成客戶希望的另一個接口,使接口不相容的那些類可以一起工作。
模式特點
擴充卡模式包含四個角色:
Target:目标抽象類,定義接口标準,用戶端可以直接調用
Adapter:擴充卡類,适配 Adaptee 與 Target,使其可以協同工作
Adaptee:适配者類,需要進行适配的接口
Client:客戶類
擴充卡模式包括兩種:
- 類結構型擴充卡:繼承關系,Adapter 同時繼承 Target 和 Adaptee 類。
- 對象結構型擴充卡:關聯關系,Adapter 繼承 Target,關聯 Adaptee。
優點
- 符合“開閉原則”,可以用配置檔案友善地更換擴充卡
- 解耦,通過引入一個擴充卡類來重用現有的适配者類
類擴充卡模式優點:
- 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