设计模式 结构型 - 适配器模式 Adapter
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的更多相关文章
- Java设计模式——结构型模式
Java设计模式中共有7种结构型模式:适配器模式.装饰模式.代理模式.外观模式.桥接模式.组合模式.享元模式.其中对象的适配器模式是各种模式的起源,其关系如下面的图:1.适配器模式 适配器模式将某个类 ...
- 设计模式系列之适配器模式(Adapter Pattern)——不兼容结构的协调
模式概述 模式定义 模式结构图 模式伪代码 类适配器,双向适配器,缺省适配器 类适配器 双向适配器 缺省适配器 模式应用 模式在JDK中的应用 模式在开源项目中的应用 模式总结 主要优点 主要缺点 适 ...
- java设计模式结构型模式
结构型模式: – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结 构,用来解决更大的问题 分类: • 适配器模式.代理模式.桥接模式. 装饰模式.组合模式.外观模式.享元模式 结构型模式 ...
- python设计模式---结构型之代理模式
主要想着nginx:) from abc import ABCMeta, abstractmethod # 结构型设计模式---代理模式 class Actor: def __init__(self) ...
- 设计模式-结构型模式,python组合模式
设计模式上大的方向上分继承和组合,就是类模式和对象模式.此篇的组合模式非继承和组合概念中的组合.桥接 策略 代理 装饰者都用了组合,此组合非彼组合. 组合模式 组合模式(Composite Patte ...
- 设计模式-结构型模式,python桥接模式
桥接模式 桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化.这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦. 这种模式涉及到一个作为桥接 ...
- c#设计模式·结构型模式
看的过程中,发现好多模式都用过,只是没有总结,或者是不知道叫这个名字吧··· 这里列举结构型模式,适配器.桥接.过滤.组合.装饰器.外观.享元.代理, 适配器模式:将现存的对象放到新的环境里边去,但是 ...
- 设计模式 结构型模式 外观模式(Facade Pattern)
在软件开发过程中,客户端程序经常会与复杂系统的内部子系统进行耦合,从而导致客户端程序随着子系统的变化而变化. 这时为了将复杂系统的内部子系统与客户端之间的依赖解耦,从而就有了外观模式,也称作 ”门面“ ...
- 设计模式---结构型模式之适配器模式(Adapter Pattern)
适配器模式定义 将一个类的接口,转换成客户期望的另外一个接口.适配器让原本接口不兼容的类可以合作无间. 适配器模式主要有两种类型:对象适配器和类适配器. 在详细解释这两种类型时,解释部分重要角色.生活 ...
随机推荐
- [codevs3044]矩形面积求并
题目描述 Description 输入n个矩形,求他们总共占地面积(也就是求一下面积的并) 输入描述 Input Description 可能有多组数据,读到n=0为止(不超过15组) 每组数据第一行 ...
- 异常CLRDBG_NOTIFICATION_EXCEPTION_CODE( 0x04242420)的抛出过程
新建一个c#控制工程,就用自动生成的代码,不用补任何代码,如下: using System; using System.Collections.Generic; using System.Linq; ...
- VUE温习:内存泄漏、Vue.$set、key作用与虚拟diff算法
一.内存泄漏 1.指令绑定了事件,却没有解绑事件,容易产生内存泄漏.(曾经遇到过的案例) 2.v-if指令产生内存泄漏,比如v-if删除了父级元素,却没有删除父级元素里的dom片段 3.跳转到别的路由 ...
- haproxy 配置文件详解 之 listen
配置示例: listen admin_stats bind mode http log 127.0.0.1 local0 err stats refresh 30s stats uri /haprox ...
- Android Studio 之 Navigation【1.页面之间的切换】
1.创建 2个 Fragment ,下面两个include 不要勾 2.创建好 Fragment 后,打开layout中的 fragment.xml 文件,将里面默认的 textView 控件删除掉 ...
- 【ASP.NET Core分布式项目实战】(四)使用mysql/mysql-server安装mysql
Docker安装Mysql 拉取镜像 docker pull mysql/mysql-server 运行mysql docker run -d -p : --name mysql01 mysql/my ...
- 【07月01日】A股滚动市净率PB历史新低排名
2010年01月01日 到 2019年07月01日 之间,滚动市净率历史新低排名. 上市三年以上的公司,2019年07月01日市净率在30以下的公司. 来源:A股滚动市净率(PB)历史新低排名. 1 ...
- cad.net 2008使用WPF(摘录山人)
由于WPF的优点多多,而且在大量的winform的操作下感觉到数据操作的麻烦....推荐大家看杨中科WPF数据绑定教程 https://www.bilibili.com/video/av3388348 ...
- Spring Cloud config之三:config-server因为server端和client端的健康检查导致服务超时阻塞问题
springcloud线上一个问题,当config-server连不上git时,微服务集群慢慢的都挂掉. 在入口层增加了日志跟踪问题: org.springframework.cloud.config ...
- HTML5 Canvas实战之刮奖效果【转】
开源项目地址:https://github.com/artwl/Lottery 作者博客地址:http://www.cnblogs.com/jscode/p/3580878.html 谢谢浏览!