Adapter(适配器模式)

---- 加个“适配器”以便于复用

将一个类的接口转换成客户希望的另一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

应用场景

  • 如果我们的代码依赖一些外部的API,或者依赖一些可能会经常更改的类,那么应该考虑用适配器模式。

  • 你想使用一个已经存在的类,而它的接口不符合你的需求

  • 你想创建一个可以复用的类,该类可以与其他不相关的类或者不可预见的类(即那些接口可能不一定兼容的类)协同工作。

  • (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。

在设计模式中,适配器模式有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类工作在一起,做法是将类自己的接口包裹在一个已存在的类中。

Adapter适配器模式包含两种:

  • 类适配器模式(使用继承的适配器)

  • 对象适配器模式(使用委托的适配器)

类适配器是通过类的继承实现的适配,而对象适配器是通过对象间的关联关系,组合关系实现的适配。二者在实际项目中都会经常用到,由于对象适配器是通过类间的关联关系进行耦合的,因此在设计时就可以做到比较灵活,而类适配器就只能通过覆写源角色的方法进行拓展,在实际项目中,对象适配器使用到的场景相对较多。

模式参与者

  • Target 目标角色 该角色定义把其他类转换为何种接口,也就是我们的期望接口。

  • Adaptee 源角色 你想把“谁”转换成目标角色,这个“谁”就是源角色,它是已经存在的、运行良好的类或对象。

  • Adapter 适配器角色 适配器模式的核心角色,其他两个角色都是已经存在的角色,而适配器角色是需要新建立的,他的职责非常简单:把源角色转换为目标角色。

类图结构

类适配器使用多重继承对一个接口与另一个接口进行匹配,如下图所示。

对象匹配器依赖于对象组合,如下图所示。

代码示例

<?php
/**
* 第一种方式:类适配器
*/
interface Adaptee {// 源角色
public function sampleMethod1();
} class Target{
public function sampleMethod2() {echo '--------';}
} class Adapter extends Target implements Adaptee {
public function sampleMethod1() {echo '++++++++';}
} $adapter = new Adapter();
$adapter->sampleMethod1();//输出:++++++++
$adapter->sampleMethod2();//输出:-------- /**
* 第二种方式:对象适配器
*/ class Adaptee { // 源角色
public function sampleMethod1() {
echo '++++++++';
}
} class Target {
public function sampleMethod2() { echo '--------';}
} class Adapter extends Target {
private $_adaptee; public function __construct(Adaptee $adaptee) {
$this->_adaptee = $adaptee;
} public function sampleMethod1() {
$this->_adaptee->sampleMethod1();
}
} $adapter = new Adapter(new Adaptee());
$adapter->sampleMethod1();//输出:++++++++
$adapter->sampleMethod2();//输出:--------
?>

适配器模式优点

  • 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成。

  • 增加了类的透明性。我们访问的是目标角色,但是实现却在源角色里。

  • 提高了类的复用度。源角色在原有系统中还是可以正常使用的。

  • 灵活性非常好。不想要适配器时,删掉这个适配器就好了,其他代码不用改。

拓展思路

  • 什么时候使用Adapter模式?

    很多时候,我们并非是从零开始编程,经常会用到现有的类。让现有的类适配新的接口API时,使用Adapter模式似乎是理所当然的。不过实际上,我们在让现有的类适配新的接口时,常常会有“只要将这里稍微修改下就可以了”的想法,一不留神就会修改现有的代码。但是需要注意的是,如果要对已经测试完毕的现有代码进行修改,就必须在修改后重新进行测试。

    使用Adapter模式就可以在完全不改变现有代码的前提下适配新的接口API。此外,在Adapter模式中,并非一定需要具体的代码。只要知道现有类的功能,就可以编写出新的类。

  • 版本升级与兼容性

    软件的生命周期总是伴随着版本的升级,而在版本升级的时候经常会出现“与旧版本的兼容性”问题。如果能够完全抛弃旧版本,那么维护起来就会轻松很多,但现实中往往无法这样做。这样,就可以使用Adapter模式使新旧版本兼容,帮助我们轻松地同时维护新旧版本。

  下面是 提高与与旧版本兼容性的Adapter模式的示意图

  

  • 功能完全不同的类 ​ 当然,当Adaptee 和 Target 的功能完全不同时,Adapter模式是无法使用的,就如同我们无法用交流100伏特电压让自来水管出水一样。

相关模式

  • Bridge 模式

    Bridge 模式的结构和对象适配器类似,但是Bridge模式的出发点不同:Bridge 目的是将接口部分和实现部分分离,从而对它们可以较为容易也相对独立的加以改变。而 Adapter 则意味着改变一个已有对象的接口。

  • Decorator 模式

    Decorator 模式增强了其他对象的功能而同时又不改变它的接口,Adpater 模式则是填补不同接口(API)之间的缝隙。

  • Proxy 模式

    Proxy 模式在不改变它的接口的条件下,为另一个对象定义了一个代理。

参考资料:

设计模式 : 可复用面向对象软件的基础

图解设计模式

兼容性:Adapter(适配器模式)【PHP】的更多相关文章

  1. C++设计模式-Adapter适配器模式

    Adapter适配器模式作用:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 分为类适配器模式和对象适配器模式. 系统的数据和 ...

  2. C++设计模式-Adapter适配器模式(转)

    Adapter适配器模式作用:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 分为类适配器模式和对象适配器模式. 系统的数据和 ...

  3. [C# 设计模式] Adapter - 适配器模式(两种)

    Adapter - 适配器模式 序 现实生活中,我们常用到适配器. 你当前打开我这篇文章的笔记本电脑,电源的另一边不正连着一块适配器吗? 你平时想将三口插座插进二口插座里面,不也需要一个适配器吗? 整 ...

  4. 设计模式06: Adapter 适配器模式(结构型模式)

    Adapter 适配器模式(结构型模式) 适配(转换)的概念无处不在:电源转接头.电源适配器.水管转接头... 动机(Motivation)在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象 ...

  5. adapter适配器模式

    适配器设计模式概述    将一个类的接口转换成另外一个客户希望的接口.从而使原来不能直接调用的接口变得可以调用 优点:    让本来不适合使用的接口变得适合使用 缺点:    一次只能适配一个类,具有 ...

  6. Adapter 适配器模式

    将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 目标接口(Target):客户所期待的接口.目标可以是具体的或抽象的类,也可 ...

  7. 设计模式(七):Adapter 适配器模式 -- 结构型模式

    1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相关库的发展和进化.  例子1:iphone4,你即可以 ...

  8. 设计模式(6)--Adapter(适配器模式)--结构型

    1.模式定义: 适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 2.模式特点:  Adapter模式使原本因接口不匹配(或者不兼 ...

  9. 设计模式C++学习笔记之八(Adapter适配器模式)

      适配器模式,使用之处比较特殊,不属于常规设计模式,主要用于不同系统之间的处理.是将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工 ...

  10. Adapter 适配器模式 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

随机推荐

  1. 修改ZendStudio新建php文件时的模板

    zendstudio默认的模板不适用,可以自己到Window -- preferences -- php -- code style -- code templates -- code -- samp ...

  2. Mysql服务启动与关闭

    启动: 在cmd中输入 net start mysql 关闭: 在cmd中输入  net stop mysql

  3. Spring Cloud微服务系统下的数据一致性探讨

    我想这个问题需要根据自己的系统具体架构来分别讨论,这边拿一个车联网的系统举例. 拆除GPS这个功能接口需要分几个步骤实现(不涉及数据更新的步骤略去了): ①更改GPS设备状态(设备管理服务) ②更改工 ...

  4. SSM-Spring-09:Spring中jdk动态代理

    ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- JDK动态代理: 为何叫JDK动态代理呢? 所谓JDK,jdk是java开发工具包,它里面包含了一个动态代理的 ...

  5. 玩转SSH--Hibernate(三)---手动修改数据库,前台查询信息不同步更新问题解决方法

    在用hibernate时遇到一个挺纠结的问题,就是我在手动修改数据库的信息后,前台页面查询到的信息还是之前的结果,一开始以为是缓存的问题,经过多次修改和在网上查询资料,最终发现可能是hibernate ...

  6. 他学习一年Python找不到工作,大佬都说你别再学Python了!

    引言: 都说,滴水穿石非一日之功.然而有些人即使奋斗一辈子也比不上别人一年,别人学习一年比不得你学习一个月.其中缘由,有些人看了大半辈子还没看明白. 即使Python这么火,为何你学习一年的Pytho ...

  7. mysql运维必会的一些知识点整理

    (1)基础笔试命令考察 1.开启MySQL服务 /etc/init.d/mysqld start service mysqld start systemctl start mysqld 2.检测端口是 ...

  8. java 自定义的注解有什么作用

    转自https://zhidao.baidu.com/question/1668622526729638507.html 自定义注解,可以应用到反射中,比如自己写个小框架. 如实现实体类某些属性不自动 ...

  9. [codeforces 804F. Fake bullions]

    题目大意: 传送门. 给一个n个点的有向完全图(即任意两点有且仅有一条有向边). 每一个点上有$S_i$个人,开始时其中有些人有真金块,有些人没有金块.当时刻$i$时,若$u$到$v$有边,若$u$中 ...

  10. BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块

    BZOJ_3809_Gty的二逼妹子序列 && BZOJ_3236_[Ahoi2013]作业 _莫队+分块 Description Autumn和Bakser又在研究Gty的妹子序列了 ...