php设计模式(八):适配器模式(Adapter)
- 陈大剩
- 2023-04-17 23:57:58
- 803
适配器模式
适配器模式又称为:封装器模式、Wrapper(包装)、Adapter。适配器是一种结构型设计模式,它能使接口不兼容的对象能够相互合作。
问题
适配器模式 在我们生活中非常常见。说到适配一词,那肯定是要去适配。
如以前的系统,需要新增加一个功能,既要保持原来的不变又要新增功能(成年人不做选择,全都要),所以需要把原来的系统功能和新增的功能用一个中间体来适配两个不同的功能,如常见的电源适配器(就是充电头),家里墙上的插孔装修完后就不在变了,手机或者电脑买回来后我们也不会去改造它,如何让不变的插孔和不变的手机之间能连上充电,并且把220V转换为5V,这时候就需要电源适配器了。
软件开发中也是同样的道理,对以前遗留下的系统,需要新增功能,所以就只能去做一些适配工作,再新增。
假设我们在现实生活中很喜欢看书,比如看(纸质书):英语书、计算机专业书、…,但是某天我们发现一本超级好看的电子书 “天龙八部”,那我们怎么像这个纸质书一样看这个电子书呢?
解决方法
看书的例子知识举例,现实生活中肯定不会出现这么傻的例子,大家都知道电子书当然只能用电子产品看,而我们软件编程就没有那么简单了,计算机只知道看纸质书,换成电子书他肯定不会看了。所以需要增加一个适配器(阅读器),让他能像看纸质书一样看电子书,你当然不能像翻纸质书一样去翻电子书吧?所以得加上一个工具。
软件开发中可以,创建适配器,能够转换成其他对象接口,使其能与其他对象进行交互,适配器将复杂的抓换过程隐藏于幕后,被封装的对象甚至察觉不到适配器的存在。
结构
.*Bbook:原本已经有的具体类;
BookInterface:目标接口;包含我们希望拥有的方法;
.*BookAdapter:适配器类;适配 Adaptee 和 Target;
代码示例
书籍基类
// BookInterface.php
interface BookInterface
{
public function turnPage();
public function open();
public function getPage(): int;
public function getInfo(): string;
}
具体数据类
/**
* EnglishBook.php
* 英语书
*/
class EnglishBook implements BookInterface
{
/**
* @var int 当前页数
*/
private $page = 0;
public function turnPage()
{
return ++$this->page;
}
public function open()
{
$this->page = 0;
return $this->page;
}
public function getPage(): int
{
return $this->page;
}
public function getInfo(): string
{
return '英语书'.PHP_EOL;
}
}
/**
* ComputerBook.php
* 计算机专业相关的书
*/
class ComputerBook implements BookInterface
{
/**
* @var int 当前页数
*/
private $page = 0;
public function turnPage()
{
return ++$this->page;
}
public function open()
{
$this->page = 0;
return $this->page;
}
public function getPage(): int
{
return $this->page;
}
public function getInfo(): string
{
return '计算机专业书'.PHP_EOL;
}
}
电子书
/**
* TianlongEBook.php
* 天龙八部电子书
*/
class TianlongEBook
{
/**
* @var int 当前页数
*/
public $page = 0;
public function turnTxtPage()
{
return ++$this->page;
}
public function openTxt()
{
$this->page = 0;
return $this->page;
}
public function getTxtPage(): int
{
return $this->page;
}
public function getTxtInfo(): string
{
return '天龙八部' . PHP_EOL;
}
}
电子书适配器
/**
* ComputerBookAdapter.php
* 适配器(电脑)
*/
class ComputerBookAdapter implements BookInterface
{
private $eBook = null;
public function __construct()
{
$eBook = new TianlongEBook();
$this->eBook = $eBook;
}
public function turnPage()
{
return $this->eBook->turnTxtPage();
}
public function open()
{
return $this->eBook->openTxt();
}
public function getPage(): int
{
return $this->eBook->getTxtPage();
}
public function getInfo(): string
{
return $this->eBook->getTxtInfo();
}
}
客户端使用
/**
* 获取计算机专业书
*/
$computerBook=new ComputerBook();
echo $computerBook->getInfo();
/**
* 获取英语专业书
*/
$englishBook=new EnglishBook();
echo $englishBook->getInfo();
/**
* 电子书查看器
*/
$computerBookAdapter=new ComputerBookAdapter();
echo $computerBookAdapter->getInfo();
输出
计算机专业书
英语书
天龙八部
UML
优缺点
优点
- 良好的单一职责原则
- 开闭原则。只要客户端代码通过适配器进行交互,就能在不修改客户端代码的情况下载程序中添加新类型的适配器
缺点
- 整体复杂度增加,需要新增适配器
当然适配器模式是处于马后炮的做法,还是在项目一开始就考虑好,那么就不会出现这种状态。