1 基础知识

定义:将一个类的接口(被适配者)转换成客户期望的另一个接口(目标)。特征:使原本接口不兼容的类可以一起工作。

本质:转换匹配,复用功能。把不兼容的接口转换为客户端期望的样子从而实现功能的复用。

使用场景:已经存在的类,它的方法(接口)和需求不匹配时的解决方案。注意适配器模式不是软件设计阶段需要考虑的设计模式,而是随着软件维护,由于不同产品不同厂家造成功能类似而接口不相同情况下的解决方案。

优点:

更好的复用:性如果功能是已经有了的,只是接口不兼容,那么通过适配器模式就可以让这些功能得到更好的复用。

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

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

2 代码示例

适配器的两种实现方式:

类适配器:

被适配者类:Adaptee

public class Adaptee {
public void adapteeRequest(){
System.out.println("被适配者的方法");
} }

目标接口:Target

public interface Target {
void request();
}

目标实现:

public class ConcreteTarget implements Target {
@Override
public void request() {
System.out.println("concreteTarget目标方法");
}
}

适配者类:Adapter  通过继承和实现将被适配者类和目标联系在了一起

public class Adapter extends Adaptee implements Target{
@Override
public void request() { //在此方法体内可以添加需要的代码 super.adapteeRequest();
}
}

应用层:

public class Test {
public static void main(String[] args) {
Target target = new ConcreteTarget();
//目标方法输出
target.request(); Target adapterTarget = new Adapter();
//适配者方法输出
adapterTarget.request();
}
}

其类图关系如下:

对象适配器:

修改适配者类:

public class Adapter implements Target{
//通过组合方式而不是继承
private Adaptee adaptee = new Adaptee(); @Override
public void request() { //添加自己需要代码 adaptee.adapteeRequest();
}
}

应用层代码不变直接测试即可,其类关系图如下图,在代码中有一个原则如果继承和组合都可以满足要求优先选择组合。

场景使用:生活中的手机充电,需要把220V转换为5V电源。

220V电源:被适配者

public class AC220 {
public int outputAC220V(){
int output = 220;
System.out.println("输出交流电"+output+"V");
return output;
}
}

目标接口:5V电源

public interface DC5 {
int outputDC5V();
}

适配者:

public class PowerAdapter implements DC5{
private AC220 ac220 = new AC220(); @Override
public int outputDC5V() {
int adapterInput = ac220.outputAC220V();
//变压器...
int adapterOutput = adapterInput/44; System.out.println("使用PowerAdapter输入AC:"+adapterInput+"V"+"输出DC:"+adapterOutput+"V");
return adapterOutput;
}
}

应用层:

public class Test {
public static void main(String[] args) {
DC5 dc5 = new PowerAdapter();
dc5.outputDC5V();
}
}

在实际开发中场景:如一个日志记录系统最初的的版本1:LogMode1 只有两个简单的功能以文件的形式读日志和写日志。

public interface LogMode1 {
public void writeLogFile();
public void readLogFile();
}

随着使用升级系统便有了版本2:将日志保存到数据库中可以对其进行增删改查

public interface LogMode12 {
//新增日志
public void creatLogFile();
//修改日志
public void updateLogFile();
//删除日志
public void removeLogFile();
//获取所有日志
public List<LogFile> getLogFile();
}

此时客户端提出需求,能否让版本2同时支持数据库存储和文件存储?直接的思路是进行合并但是有问题,现在客户端操作的第二版的日志接口,但第一版的接口与第二版的不同,客户端无法以同样的方式使用第一版的实现,如下图所示:

简单粗暴的方法是在第二版中增加文件存储功能,但是这些功能在第一版中已经实现过了,因此要避免重复劳动。解决方法就是采用适配器模式:Target接口相当于第二版的日志接口,被适配者则是第一版接口,采用类似前面提供的代码即可解决。

3 源代码中的使用

4 相关设计模式

(1)适配器模式与桥接模式

其实这两个模式除了结构略为相似外,功能上完全不同。适配器模式是把两个或者多个接口的功能进行转换匹配;而桥接模式是让接口和实现部分相分离,以便它们可以相对独立地变化。

(2)适配器模式与装饰模式

从某种意义上讲,适配器模式能模拟实现简单的装饰模式的功能,也就是为已有功能增添新功能,因为在适配器里可以添加功能。但仅仅是类似,造成这种类似的原因是:两种设计模式在实现上都是使意用的对象组合,都可以在转调组合对象的功能前后进行一些附加的处理,因此有这么一个相似性。它们的目的和本质都是不一样的。两个模式有一个很大的不同:一般适配器适配过后是需要改变接口的,如果不改接口就没有必要适配了;而装饰模式是不改变接口的,无论多少层装饰都是一个接口。因此装饰模式可以很容易地支持递归组合,而适配器就做不到,每次的接口不同,无法递归。

(3)适配器模式和代模式

适配器模式可以和代理模式组合使用。在实现近配器的时候,可以通过代理来调用 Adaptee,这样可以获得更大的灵活性。

(4)适配器模式和抽象工厂模式。

在适配器实现的时候,通常需要得到被适配的对象。如果被适配的是一个接口,那么就可以结合一些可以创造对象实例的设计模式,来得到被适配的对象示例,比如抽象工厂模式、单例模式、工厂方法模式等。

0

适配器模式(Adapter)---结构型的更多相关文章

  1. 适配器模式 adapter 结构型 设计模式(九)

    现实世界中的适配器模型   先来看下来几个图片,截图自淘宝 上图为港版的插头与港版的插座   上图为插座适配器卖家的描述图   上图为适配后的结果 现实世界中适配器模式 角色分类 这就是适配器模式在电 ...

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

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

  3. Java设计模式06:常用设计模式之适配器模式(结构型模式)

    1. Java之适配器模式(Adapter Pattern) (1)概述:    将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类,可以在一起 ...

  4. C#设计模式--适配器模式(结构型模式)

    一.适配器模式介绍: 适配器模式:将一个类的接口,转换成客户希望的另外一个接口.adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 例子分析(充电器充电): 模式中的角色: 安 ...

  5. 设计模式之适配器模式(Adapter)

    适配器模式原理:适配器模式属于结构型模式,主要作用是完成功能的转换, 1.通过一个类继承目标类. 2.需要适配的类 3.适配器 代码如下: #include <iostream> usin ...

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

      设计模式(五)适配器模式Adapter(结构型) 1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相 ...

  7. C#设计模式之七适配器模式(Adapter)【结构型】

    一.引言   从今天开始我们开始讲[结构型]设计模式,[结构型]设计模式有如下几种:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式.[创建型]的设计模式解决的是对象创建的问题, ...

  8. C#设计模式之六适配器模式(Adapter Pattern)【结构型】

    一.引言 从今天开始我们开始讲[结构型]设计模式,[结构型]设计模式有如下几种:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式.[创建型]的设计模式解决的是对象创建的问题,那[ ...

  9. NET设计模式 第三部分 结构型模式(7):适配器模式(Adapter Pattern)

    适配器模式(Adapter Pattern) ——.NET设计模式系列之八 Terrylee,2006年2月 概述 在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但 ...

  10. 初探Java设计模式2:结构型模式(代理模式,适配器模式等)

    行为型模式 行为型模式关注的是各个类之间的相互作用,将职责划分清楚,使得我们的代码更加地清晰. 策略模式 策略模式太常用了,所以把它放到最前面进行介绍.它比较简单,我就不废话,直接用代码说事吧. 下面 ...

随机推荐

  1. nginx文件服务器搭建

    一.安装 (CentOS 7) yum install nginx -y 如果报错: [u3@L3 /]$ sudo yum install nginx -y Loaded plugins: fast ...

  2. pymysql连接和操作Mysql数据库

    pymysql 一.概要 PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库, 二.PyMySQL 安装 pip install pymysql 三.操作流程 创建c ...

  3. [游戏复刻] Super Mario Brothers(1985. Famicom)

    10/20 第一版,导入了地图,设置了碰撞块

  4. php 求两个数组的差集应该注意的事情

    对于 phper 来说 array_diff 这个函数应该知道它的用途,获取两个数组的差集,我理解中的差集是这样的 但是执行下代码会发现结果并不是 <?php $a = [1,2,3,4,5]; ...

  5. golang数据基本数据类型和string类型的转换

    基本类型之间的转换 golang在不同类型的变量之间赋值时需要显式转换,也就是说golang中数据类型不能自动转换. 表达式T(v)将值v转换为类型T 1.数据类型的转换可以是从范围小——>范围 ...

  6. 第四章 MIZ701 ZYNQ制作UBOOT固化程序

      4.0难度系数★☆☆☆☆☆☆ 4.1是什么是固化 我们前几章将的程序都是通过JTAG先下载bit流文件,再下载elf文件,之后点击Run As来运行的程序.JTAG的方法是通过TCL脚本来初始化P ...

  7. poj 1753高斯

    和前面的开关问题差不多,就是要理解一下我们方程等号的右端代表的含义是什么.我们建立的方程是想让对位的位置变或者不变,然后生成增广矩阵的时候要多注意一点. ac代码: #include #include ...

  8. 在开源UOJ的导航栏中添加新页面链接

    前言 刚用开源UOJ搭建OJ成功时就想在导航栏那里添加一个站内页面链接,无奈当时乱搞水平低,网上也没有教程,不晓得怎么弄 今天突然来了闲情乱搞一通,结果还真乱搞成了...特意写下为后来人少走点弯路 前 ...

  9. 6.Cookie和Session

    /*会话*/ (开一个浏览器,访问几个web资源,然后关闭浏览器,这个过程为一个对话) /*保存*/会话数据的两种技术(cookie session) 1.Cookie (客户端技术)(数据保存在客户 ...

  10. 学习记录--JVM内存分析

    今天刷牛客网的题时,看到了两位大神关于JVM内存分析的讲解,就顺手记录学习一下. JVM内存模型图 方法区域存放了所加载的类的信息(名称.修饰符等).类中的静态变量.类中定义为final类型的常量.类 ...