[toc]
## 舉個例子
> **身高不夠鞋來湊**
> 身材苗條、長像出眾是每個人夢寐以求的,尤其是女孩子!但很多人卻因為先天的原因并不能如意,這時就需要通過服裝、化妝去彌補。
> 所謂美女,三分靠長相七分靠打扮!比如身高不夠,就可以通過穿高跟鞋來彌補
> 這里的高跟鞋就起著一個適配的作用,能讓你的形象增高四、五厘米
## 代碼實現
```php
<?php
interface IHightPerson {
public function getName();
public function getHeight();
}
class HighPerson implements IHightPerson {
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getHeight() {
return 170;
}
}
class ShortPerson {
protected $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function getRealHeight() {
return 160;
}
public function getShoeHeight() {
return 6;
}
}
class DecoratePerson extends ShortPerson {
public function getHeight() {
return parent::getRealHeight() + parent::getShoeHeight();
}
}
function canPlayReceptionist($person) {
return $person->getHeight() >= 165;
}
function testPerson() {
$lira = new HighPerson("Lira");
echo $lira->getName() . "身高" . strval($lira->getHeight()) . ",完美如你,天生的美女!";
$res = "是否適合做接待員:";
if (canPlayReceptionist($lira)) {
echo $res . "符合";
} else {
echo $res . "不符合";
}
echo PHP_EOL;
$demi = new DecoratePerson('Demi');
echo $demi->getName() . "身高" . strval($demi->getHeight()) . ",在高跟鞋的適配下,你身高不輸高圓圓,氣質不輸范冰冰!";
if (canPlayReceptionist($demi)) {
echo $res . "符合";
} else {
echo $res . "不符合";
}
}
testPerson();
```
```
D:\soft\php72\php.exe D:\project\php_dp\index.php
Lira身高170,完美如你,天生的美女!是否適合做接待員:符合
Demi身高166,在高跟鞋的適配下,你身高不輸高圓圓,氣質不輸范冰冰!是否適合做接待員:符合
Process finished with exit code 0
```
> 在上面的例子中,高跟鞋起著一個適配的作用,讓其形象增高 5~7 厘米完全不在話下,而且效果立竿見影!使得一些女孩原本不符合接待員的真實身高,在鞋子的幫助下也能符合條件。
> 如高跟鞋一樣,使原本不匹配某種功能的對象變得匹配這種功能,這在程序中叫做適配器模式。
## 什么是適配模式
> 將一個類的接口變成客戶端所期望的另一種接口,從而使原本因接口不匹配而無法一起工作的兩個類能夠在一起工作。
## 適配器模式的作用:
1. 接口轉換,將原有的接口(或方法)轉換成另一種接口;
1. 用新的接口包裝一個已有的類;
1. 匹配一個老的組件到一個新的接口。


## 設計要點
> 配器模式中主要三個角色,在設計適配器模式時要找到并區分這些角色:
1. **目標(Target)**: 即你期望的目標接口,要轉換成的接口。
1. **源對象(Adaptee)**: 即要被轉換的角色,要把誰轉換成目標角色。
1. **適配器(Adapter)**: 適配器模式的核心角色,負責把源對象轉換和包裝成目標對象。
## 實戰應用
> 有一個電子書閱讀器的項目(Reader),研發之初,產品經理經過各方討論,最后告訴我們只支持 TXT 和 Epub 格式的電子書。
> 然后經過仔細思考、精心設計,采用了如圖1的代碼架構。
> 在這個類圖中,有一個閱讀器的核心類 Reader,一個 TXT 文檔的關鍵類 TxtBook(負責 TXT 格式文件的解析),和一個 Epub 文檔的關鍵類 EpubBook(負責 Epub 格式文件的解析)。

圖1:閱讀器類圖
> 產品上線半年后,市場響應良好,業務部門反映:有很多辦公人員也在用我們的閱讀器,他們希望這個閱讀器能同時支持 PDF 格式,這樣就不用在多個閱讀器神之間來回切換了,
> 此時程序就需要增加對 PDF 格式的支持,而 PDF 并不是核心業務,我們不會單獨為其開發一套 PDF 解析內核,而會使用一些開源的 PDF 庫(我們稱它為第三方庫),如 MuPDF、TCPDF 等。而開源庫的接口和我們的接口并不相同(如圖2),返回的內容也不是我們直接需要的,需要經過一些轉換才能符合我們的要求。

圖2:第三方 PDF 解析庫的類圖
> 這時,我們就需要對 PDF 的解析庫 MuPDF 進行適配。經過上面的學習,你一定知道這時該用適配器模式了,于是有了如下圖3的類圖結構。

圖3:兼容 PDF 的類圖結構