Java 设计模式系列(六)适配器模式

适配器模式把一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

适配器模式的结构:

  1. 类的适配器模式
  2. 对象的适配器模式

一、类适配器模式

类的适配器模式把适配的类的 API 转换成为目标类的 API。

在上图中可以看出,Adaptee 类并没有 sampleOperation2() 方法,而客户端则期待这个方法。为使客户端能够使用 Adaptee 类,提供一个中间环节,即类 Adapter,把 Adaptee 的 API 与 Target 类的 API 衔接起来。Adapter 与 Adaptee 是继承关系,这决定了这个适配器模式是类的:

模式所涉及的角色有:

(1)目标(Target)角色:这就是所期待得到的接口。注意:由于这里讨论的是类适配器模式,因此目标不可以是类。

(2)源(Adapee)角色:现在需要适配的接口。

(3)适配器(Adaper)角色:适配器类是本模式的核心。适配器把源接口转换成目标接口。显然,这一角色不可以是接口,而必须是具体类。

源代码

public interface Target {

    /** 这是源类Adaptee也有的方法 */
public void sampleOperation1(); /** 这是源类Adapteee没有的方法 */
public void sampleOperation2();
}

上面给出的是目标角色的源代码,这个角色是以一个 JAVA 接口的形式实现的。可以看出,这个接口声明了两个方法:sampleOperation1() 和 sampleOperation2() 。而源角色 Adaptee 是一个具体类,它有一个 sampleOperation1() 方法,但是没有 sampleOperation2() 方法。

public class Adaptee {

    public void sampleOperation1(){}
}

适配器角色Adapter扩展了Adaptee,同时又实现了目标(Target)接口。由于Adaptee没有提供sampleOperation2()方法,而目标接口又要求这个方法,因此适配器角色Adapter实现了这个方法。

public class Adapter extends Adaptee implements Target {

    /**
* 由于源类 Adaptee 没有方法 sampleOperation2()
* 因此适配器补充上这个方法
*/
@Override
public void sampleOperation2() {
//写相关的代码
}
}

二、对象的适配器模式

与类的适配器模式一样,对象的适配器模式把被适配的类的 API 转换成为目标类的 API,与类的适配器模式不同的是,对象的适配器模式不是使用继承关系连接到 Adaptee 类,而是使用委派关系连接到 Adaptee 类。

public interface Target {

    /** 这是源类Adaptee也有的方法 */
public void sampleOperation1(); /** 这是源类Adapteee没有的方法 */
public void sampleOperation2();
} public class Adaptee { public void sampleOperation1(){}
} public class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee){
this.adaptee = adaptee;
} /** 源类 Adaptee 有方法 sampleOperation1,因此适配器类直接委派即可 */
public void sampleOperation1(){
this.adaptee.sampleOperation1();
} /** 源类 Adaptee 没有方法 sampleOperation2,因此由适配器类需要补充此方法 */
public void sampleOperation2(){
//写相关的代码
}
}

建议尽量使用对象适配器的实现方式,多用合成/聚合、少用继承。

三、缺省适配模式的结构

缺省适配模式是一种“平庸”化的适配器模式。

public interface AbstractService {
public void serviceOperation1();
public int serviceOperation2();
public String serviceOperation3();
}
public class ServiceAdapter implements AbstractService{

    @Override
public void serviceOperation1() {
} @Override
public int serviceOperation2() {
return 0;
} @Override
public String serviceOperation3() {
return null;
} }

可以看到,接口 AbstractService 要求定义三个方法,分别是 serviceOperation1()、serviceOperation2()、serviceOperation3();而抽象适配器类 ServiceAdapter 则为这三种方法都提供了平庸的实现。因此,任何继承自抽象类 ServiceAdapter 的具体类都可以选择它所需要的方法实现,而不必理会其他的不需要的方法。

适配器模式的用意是要改变源的接口,以便于目标接口相容。缺省适配的用意稍有不同,它是为了方便建立一个不平庸的适配器类而提供的一种平庸实现。

在任何时候,如果不准备实现一个接口的所有方法时,就可以使用“缺省适配模式”制造一个抽象类,给出所有方法的平庸的具体实现。这样,从这个抽象类再继承下去的子类就不必实现所有的方法了。

适配器模式的优缺点

适配器模式的优点

  1. 更好的复用性

      

    系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。

  2. 更好的扩展性

    在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。

适配器模式的缺点

过多的使用适配器,会让系统非常零乱,不易整体进行把握。比如,明明看到调用的是 A 接口,其实内部被适配成了 B 接口的实现,一个系统如果太多出现这种情况,无异于一场灾难。因此如果不是很有必要,可以不使用适配器,而是直接对系统进行重构。


每天用心记录一点点。内容也许不重要,但习惯很重要!

Java 设计模式系列(六)适配器模式的更多相关文章

  1. Java设计模式系列之适配器模式

    适配器模式的定义 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.(就类似于我们充电器的转接头将220V的电压转换成我们的手机端 ...

  2. Java设计模式系列-装饰器模式

    原创文章,转载请标注出处:<Java设计模式系列-装饰器模式> 一.概述 装饰器模式作用是针对目标方法进行增强,提供新的功能或者额外的功能. 不同于适配器模式和桥接模式,装饰器模式涉及的是 ...

  3. Java设计模式系列-抽象工厂模式

    原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755412.html 一.概述 抽象工厂模式是对工厂方法模式的再升级,但是二者面对的场景稍显差别. ...

  4. Java设计模式系列-工厂方法模式

    原创文章,转载请标注出处:<Java设计模式系列-工厂方法模式> 一.概述 工厂,就是生产产品的地方. 在Java设计模式中使用工厂的概念,那就是生成对象的地方了. 本来直接就能创建的对象 ...

  5. Java 设计模式系列(二三)访问者模式(Vistor)

    Java 设计模式系列(二三)访问者模式(Vistor) 访问者模式是对象的行为模式.访问者模式的目的是封装一些施加于某种数据结构元素之上的操作.一旦这些操作需要修改的话,接受这个操作的数据结构则可以 ...

  6. Java 设计模式系列(十五)观察者模式(Observer)

    Java 设计模式系列(十五)观察者模式(Observer) Java 设计模式系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Java ...

  7. Java 设计模式系列(十八)备忘录模式(Memento)

    Java 设计模式系列(十八)备忘录模式(Memento) 备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式.备忘录对象是一个用来存储另外一个对象内部状态 ...

  8. Java 设计模式系列(二十)状态模式

    Java 设计模式系列(二十)状态模式 状态模式,又称状态对象模式(Pattern of Objects for States),状态模式是对象的行为模式.状态模式允许一个对象在其内部状态改变的时候改 ...

  9. Java 设计模式系列(十五)迭代器模式(Iterator)

    Java 设计模式系列(十五)迭代器模式(Iterator) 迭代器模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象(interna ...

随机推荐

  1. 重新学习之spring第四个程序,整合struts2+hibernate+spring

    第一步:导入三大框架的jar包(struts2.3.16.1+hibernate3.2+spring3.2.4) 第二步:编写web.xml 和struts.xml和applicationContex ...

  2. python中如何将两个list合并成一个list,不用for语句

    1, add 2, 用list的extend方法,L1.extend(L2),该方法将参数L2的全部元素添加到L1的尾部,例如: 3, 用切片(slice)操作,L1[len(L1):len(L1)] ...

  3. docker 数据卷 ---- 进阶篇

    笔者在<Docker 基础 : 数据管理>一文中介绍了 docker 数据卷(volume) 的基本用法.随着使用的深入,笔者对 docker 数据卷的理解与认识也在不断的增强.本文将在前 ...

  4. MySQL 数据类型(float)的注意事项

    摘要:      今天左哥问起一个float浮点数类型的问题,这个类型用的不多,所以也不太了解,现在打算测试下. 知识点:      float:浮点数,单精度,占4字节. 测试 root@local ...

  5. java 题

    [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析:   兔子的规律为数列1 ...

  6. CentOS 7 安装Memcached服务

    Memcached 简介 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站 ...

  7. Navicat Premium解决连接mssql报错的问题

    连接名:mssql_172.16.30.21:1433,每次打开查询时就报错. 重启,重转都不好使. 解决办法:去掉“:1433”,因为文件目录不支持“:”,所以一直报错.问题终于得到解决.

  8. 腾讯互娱开源分布式开发框架Pebble

    构建游戏世界的Pebble 愿景:出色的游戏服务器端底层框架   现代游戏项目中,为了让更多的玩家能在一起玩,游戏服务器所需要承载的在线玩家数量越来越多.同时为了让游戏更好玩,越来越多复杂的业务逻辑都 ...

  9. YUM CentOS 7 64位下mysql5.7安装配置

    配置YUM源 在MySQL官网中下载YUM源rpm安装包:http://dev.mysql.com/downloads/repo/yum/ #下载mysql源安装包 # wget http://dev ...

  10. react之echarts数据更新

    react之echarts数据更新 在使用setState更新数据时,如果要将图标更新,需要做一些简单的封装,代码如下: import React, { Component } from 'react ...