文档章节

适配器模式(Adapter Pattern 类对象结构型模式)

翰霖学院
 翰霖学院
发布于 2017/07/24 08:59
字数 1932
阅读 3
收藏 0

意图

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

适用性

以下情况使用Adapter模式:
1. 你想使用一个已经存在的类,而它的接口不符合你的要求
2. 你想创建一个可以复用的类,该类可以与其他不相关的类或不可预见的类(即那些接口可能不一定兼容的类)协同工作。
3. (仅适用于对象Adapter)你想使用一些已经存在的子类,但是不可能对每一个都进行子类化以匹配它们的接口。对象适配器可以适配它的父类接口。
4. 想使用一个已经存在的类,但如果它的接口和你的要求不相同时。可以使用适配器模式。两个类所做的事情相同或相似,但接口不同时可以使用。

结构

这里写图片描述

参与者

Target

定义Client使用的与特定领域相关的接口。

Client

与符合Target接口的对象协同

Adaptee

定义一个已经存在的接口,这个接口需要适配

Adapter

对Adaptee的接口与Target接口进行适配

代码

public class Adaptee {
    public void oldMethod(){
        System.out.println("===Adaptee===oldMethod====");
    }
}
public interface Target {
    public void newMethod();
}
public class Adapter implements Target{
    private Adaptee adaptee;
    public Adapter(Adaptee adaptee){this.adaptee = adaptee;}
    public void newMethod() {
        adaptee.oldMethod();
        System.out.println("===Adapter===newMethod====");       
    }
}
public class Client {
    public static void main(String[] args) {
        Target target = new Adapter(new Adaptee());
        target.newMethod();
    }
}

协作

Client在Adapter实例上调用一些操作。接着适配器调用Adaptee的操作实现这个请求。

类对象适配器对比

类适配器

  1. 用一个具体的Adapter类对Adaptee和Target进行匹配。结果是当我们想要匹配一个类似以及所有它的子类时,类Adapter将不能胜任工作。
  2. 使得Adapter可以重定义Adaptee的部分行为,因为Adapter是Adaptee的一个子类
  3. 仅仅引入一个对象,并不需要额外的指针以简洁得到adaptee

对象适配器

  1. 允许一个Adapter与多个Adptee,即Adaptee本身以及它的所有子类(如果有子类的话),同时工作。Adapter也可以一次给所有的Adaptee添加功能。
  2. 使得重定义Adaptee的行为比较困难。这就需要生产Adaptee的子类并且使用Adapter引用这个子类而不是引用Adaptee本身。

效果

Adapter的匹配程度

对于Adaptee的接口与Target的接口进行匹配的工作量各个Adapter可能不一样。工作范围可能是,从简单的接口转换(例如改变操作名)到支持完全不同的操作集合。Adapter的工作量取决于Target接口与Adaptee接口的相似程度。

可插入的Adapter(内部接口适配器)

当其他的类使用一个类时,如果所需的假定条件越少,这个类就更具可复用性。如果将接口匹配构建为一个类,就不需要假定对其他的类可见的是一个相同的接口。也就是说,接口匹配使得我们可以将自己的类加入到一些现有的系统中去,而这些系统对这个类的接口可能会有所不同。

使用双向适配器提供透明操作

使用适配器的一个潜在问题是,它们不对所有的客户都透明。被适配的对象不再兼容Adaptee的接口,因此并不是所有的Adaptee对象可以被使用的地方都可以被使用。双向适配器提供了这样的透明性。在两个不同的客户需要用不同的方式查看同一个对象时,双向适配器尤其有用。

优点

  1. 将目标类和适配者类解耦
  2. 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性
  3. 灵活性和扩展性都非常好,符合开闭原则

缺点

一次最多只能适配一个适配者类,而且目标抽象类只能为接口,不能为类,其使用有一定的局限性,不能将一个适配者类和他的子类同时适配到目标接口。

实现

使用C++实现适配器

在使用C++实现适配器类时,Adapter类应该采用公共方法继承Target,并且用私有方式继承Adaptee类。因此,Adapter类应该是Target的子类型,但不是Adaptee的子类型。

可插入的适配器

窄接口

首先(这也是所有者三种实现都要做的)是为Adaptee找到一个“窄”接口,即可用于适配最小操作集。因为包含较少操作的窄接口相对包含校对操作的宽接口比较容易进行匹配。最小接口集仅包含两个操作:一个操作定义如何在层次接口中表示一个节点,另一个操作返回该节点的子节点。
实现方式:
1. 使用抽象操作:在TreeDisplay中定义窄Adaptee接口相应的抽象操作。这样就由子类来实现这些抽象操作并匹配具体的树形结构的对象。

  1. 使用代理对象:这种方法中,TreeDisplay将访问树结构的请求转发到代理对象。TreeDisplay的客户进行一些选择,并将这些选择提供给代理对象,这样客户就可以对适配加以控制

  2. 参数化的适配器:通常在Smalltalk中支持可插入适配器的方法是,用一个或多个模块对适配器进行参数化。模块构造支持无子类的适配。一个模块可以匹配一个请求,并且适配器可以为每个请求存储一个模块。在本例中意味着,TreeDisplay存储的一个模块用来将一个节点转化成一个GraphicNode,另外一个模块用来存取一个节点的子节点。如果你在一个类中创建接口适配,这种方法提供了另外一种选择,它相对于子类化方法来说更方便一些。

经典例子

电源适配器

Java IO

这里写图片描述

相关模式

Bridge Pattern

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

Decorator Pattern

Decorator模式增强了其他对象的功能而同时不改变它的接口。因此decorator对应用程序的透明性比适配器更好。结果是decorator支持递归组合,而纯粹使用适配器是不可能实现这一点的。Adapter是填补接口之间的差距,Decorator是不需要修改接口即可新增功能的Pattern。

Proxy Pattern

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

敬请期待“门面模式(Facade 外观模式,对象结构型模式)”

© 著作权归作者所有

共有 人打赏支持
翰霖学院
粉丝 0
博文 67
码字总数 45112
作品 0
济南
高级程序员
【设计模式】适配器模式 Adapter Parttern

适配器模式在软件开发界使用及其广泛,在工业界,现实中也是屡见不鲜。比如手机充电器,笔记本充电器,广播接收器,电视接收器等等。都是适配器。 适配器主要作用是让本来不兼容的两个事物兼...

风之源
08/08
0
0
设计模式梳理(一)

设计模式梳理(一) 总体来说设计模式分为三大类: @案例源码地址:https://gitlab.com/lxqxsyu/DisgnPattern 创建型模式 简单工厂模式 工厂类是整个模式的关键。它包含必要的判断逻辑,能够...

lxq_xsyu
2017/11/02
0
0
设计模式笔录(二),设计模式有哪些

本人出道5年,学习、编程、再学习、再编程一路走过,只是在笔和纸留下些脚印,实感惭愧。现开始把自己学习到的心得,实践中的体会,一一贴在互联网上,大家互相学习、探讨,寻找一些技术朋友...

方旭
2011/03/31
0
0
小菜学设计模式——设计模式总结之结构型

1、设计模式总结 设计模式总共23个,但是常用的不到10个,下面就把这23个设计模式进行整理归类,具体如下: 1)创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型...

learn_more
2015/07/06
0
0
JavaScript常用设计模式

设计模式 设计模式是一种在长时间的经验与错误中总结出来可服用的解决方案。 设计模式主要分为3类: 创建型设计模式:专注于处理对象的创建 Constructor构造器模式,Factory工厂模式,Singl...

a独家记忆
07/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

函数调用约定 (cdecl stdcall)

函数调用约定 (cdecl stdcall) 在 C 语言里,我们通过阅读函数声明,就知道怎么携带参数去调用函数,也能在函数体定义内使用这些参数。但是 CPU 并不直接完成函数调用的传参操作,这需要人为...

傅易
5分钟前
0
0
Python 核心编程 (全)

浅拷贝和深拷贝 1.浅拷贝:是对于一个对象的顶层拷贝,通俗的理解是:拷贝了引用,并没有拷贝内容。相当于把变量里面指向的一个地址给了另一个变量就是浅拷贝,而没有创建一个新的对象,如a=b...

代码打碟手
7分钟前
0
0
mysql5.7 修改datadir

mysql 的默认存储路径为 /var/lib/mysql ,修改后为 /data/mysql 关闭服务 service mysql stop 复制mysql 数据文件到新的目录 cp -rp /var/lib/mysql /data 查看原目录的权限,如果新目...

hotsmile
24分钟前
0
0
证书安装指引之Tomcat 证书部署

Tomcat 证书部署 0 申请证书 1 获取证书 如果申请证书时有填写私钥密码,下载可获得Tomcat文件夹,其中有密钥库 www.domain.com.jks; 如果没有填写私钥密码,证书下载包的Tomcat文件夹中包括...

吴伟祥
28分钟前
0
0
ConcurrentHashMap1.7和1.8的底层不同实现

1.Hashmap和HashTable在线程安全方面的优劣? Hashmap多线程会导致HashMap的Entry链表形成环形数据结构,一旦形成环形数据结构,Entry的next节点永远不为空,就会产生死循环获取Entry。 Hash...

刘祖鹏
44分钟前
9
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部