官方定义
适配器模式的英文翻译是Adapter Design Pattern。顾名思义,这个模式就是用来适配的,它将不兼容的接口转换为可兼容的接口,让原本由于接口不兼容而不能一起工作的类可以一起工作。
核心
在原有的接口或类的外层封装了一个新的适配器层,以实现扩展对象结构的效果,并且这种扩展可以无限扩展下去。
应用场景
- 封装有缺陷的接口设计
- 统一多个类的接口设计
- 替换依赖的外部系统
- 兼容老版本接口
- 适配不同格式的数据
封装有缺陷的接口设计
我们来看看下面两个例子:① 类适配器 ② 对象适配器
// 原先的插口是圆形的我们使用继承去处理它 这种的学名叫做类适配器 不推荐使用
class Socket
{
public function circular() {
echo '圆形插口'. "\r\n";
}
}
// 目标接口需要的是要满足圆形和正方形
interface Itarget
{
public function circular();
public function square();
}
// 适配器角色继承Socket 然后实现了正方形的接口
class SocketAdapter extends Socket implements Itarget
{
public function square()
{
echo '正方形插口'."\r\n";
}
}
$socketAdapter = new SocketAdapter();
$socketAdapter->square();
$socketAdapter->circular();
// 输出内容
···
正方形插口
圆形插口
···
// 对象适配器 我们可以将上面的继承的方式改为更加灵活的组合模式。
// 原先的插口是原型的
class Socket
{
public function circular() {
echo '圆形插口'. "\r\n";
}
}
// 目标接口需要的是要满足圆形和正方形
interface Itarget
{
public function circular();
public function square();
}
// 适配器角色继承Socket 然后实现了正方形的接口
class SocketAdapter implements Itarget
{
protected $socket;
public function __construct(Socket $socket)
{
$this->socket = $socket;
}
public function circular()
{
$this->socket->circular();
}
public function square()
{
echo '正方形插口'."\r\n";
}
}
$socketAdapter = new SocketAdapter(new Socket());
$socketAdapter->square();
$socketAdapter->circular();
// 输出内容
···
正方形插口
圆形插口
···
小结
从上面的例子我们可以看出,其实适配器角色就相当于一个中间层进行了转换的作用。举个具象的例子就是 苹果手机大家都知道它的新出厂的型号是不支持直接插耳机的,但是经过研究我们在不改变手机的整体结构的前提下,新增加了一个转接的接口,这样我们就可以在手机上使用有线耳机了。
为什么要使用适配器模式?
- 原有接口无法修改但又必须快速兼容部分新功能
- 需要使用外部组件组合成新组件来提供功能,而又不想重复开发部分功能。
- 不同数据格式,不同协议需要转换。
优点
- 将目标类和具体适配者类解耦
- 增加了类的透明性
- 满足里氏替换原则
- 符合开闭原则
- 统一多个类或者接口
缺点
- 一次只能适配一个抽象类或接口
- 过度嵌套会导致接口臃肿
- 目标接口依赖太多适配器接口,修改目标接口会导致所有适配器接口都需要定制修改。
总结
由于结构性设计模式设计如何组合更多的对象来提升代码结构的灵活性,因此在学习所有结构性设计模式的时候,都要努力建立一个大局观,也就是要多从整体程序设计的大结构去考虑模式应用的场景,不要过度纠结于局部是不是满足模式