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. 学习Layui 第一天

    Layui 官网说这是款经典模块化前端框架 个人觉得Layui很好用,容易上手. 在学习Layui的之前.先去官网下载必要的文件 将这些文件放入项目当中 然后可以到官网看一下示例. 可以做一个简单的表 ...

  2. SSM-SpringMVC-02:SpringMVC最简单的小案例

     ------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 咱们这个案例做什么? 就是用处理器代替Servlet处理请求 开发步骤: 1.引入jar包 <!--单 ...

  3. Deep Learning Enables You to Hide Screen when Your Boss is Approaching

    https://github.com/Hironsan/BossSensor/ 背景介绍 学生时代,老师站在窗外的阴影挥之不去.大家在玩手机,看漫画,看小说的时候,总是会找同桌帮忙看着班主任有没有来. ...

  4. 一个相对健壮的node 静态http服务器

    先上代码,然后说说坑,算是一个总结,以后在mac上就用这个开启服务调试了,挺好.然后接着想写一个动态的返回页面的,刚好练手mv*的框架. var http = require('http'); var ...

  5. mac升级到php7

    使用homebrew安装php7 brew update #更新源 brew search php #查找源中的php,发现有php7.1版本,安装最新的php7.1 brew install php ...

  6. 35.app后端搜索入门

    现在人们的网络生活已经离不开搜索了,遇到不懂的问题,想知道的事情,搜索一下,就知道答案. 在app中,最常见的搜索情景就是搜索用户.只有几百,几千的用户量时,可以直接用用like这样的模糊查询,但是, ...

  7. Yii整合ucenter实现单点登录

    原文:http://www.php2.cc/article-1349-1.html 准备工作 1.下载ucenter源码,并安装好 2.下载ucenter开发源码,根据自己的项目下载对应版本(utf- ...

  8. TestNG exception

    以下内容引自: https://howtodoinjava.com/testng/testng-expected-exception-and-expected-message-tutorial/ Ho ...

  9. PLINQ的 ForAll 对比集合的ForEach

    在 PLINQ 中,还可以使用 foreach 执行查询以及循环访问结果. 但是,foreach 本身不会并行运行,因此,它要求将所有并行任务的输出合并回该循环正在上面运行的线程中. 在 PLINQ ...

  10. MyBatis 中@param 的用法

    示例: 接口方法 public List<Teacher> selectTeacher(@Param(value="id") String id,@Param(valu ...