网上看到不少关于适配器模式的讲解,其中对于适配器模式解释的过于专业,一时不是特别理解适配器模式到底是用来干嘛的,具体的适用场景在哪,其最精髓的地方到底在哪。

本文结合自己的理解,阐述下对适配器模式的看法。

假设系统存在一个现有的类UserInfo:

 class UserInfo {

     private Map<String, String> userBaseInfo;

     public Map getUserBaseInfo() {
return userBaseInfo;
} public void setUserBaseInfo(Map<String, String> userBaseInfo) {
this.userBaseInfo = userBaseInfo;
}
}

客户端可以通过如下方式set、get员工基本信息:

 public class AdapterTest {

     public static void main(String[] args) {

         UserInfo oui = new UserInfo();
Map<String, String> inUserInfo = new HashMap<String, String>() {
{
put("name", "corn");
put("telNumber", "170xxxxxxxx");
}
};
oui.setUserBaseInfo(inUserInfo); // 原有取得员工基本信息的方式
Map<String, String> outUserInfo = oui.getUserBaseInfo();
String name = outUserInfo.get("name");
String telNumber = outUserInfo.get("telNumber"); }
}

有一天,基于某种原因(也许你看着这种取数据的方式不太爽,也许是系统间数据交换的原因等),你需要按照如下接口的方式取数据:

目标员工接口:

 interface UserInterface {

     public String getName();

     public String getTelNumber();

 }

那么,现在的问题是,如何将一个既定的类转换成按照目标接口的所期望的行为形式呢?

具体怎样实现呢,可以通过如下方式进行:

 class UserAdapter extends UserInfo implements UserInterface {

     @Override
public String getName() {
return (String) super.getUserBaseInfo().get("name");
} @Override
public String getTelNumber() {
return (String) super.getUserBaseInfo().get("telNumber");
} }

从上面的UserAdapter类定义中我们发现,UserAdapter不仅实现了UserInterface接口,同时还继承了UserInfo类。在实现接口的getName()和getTelNumber()方法中,分别调用了UserInfo类中的相应方法并取得结果。由此可以满足需求。在上述定义中,按照UserInterface、UserInfo和UserAdapter在场景中的目的不同,可以具体划分成如下角色:

UserInterface:目标角色——目标接口,系统所期待实现的目标;

UserInfo:源角色——当前已经存在的原有的实现类,即将被适配的类;

UserAdapter:适配器角色——将原有实现装换为目标接口的实现。

简单点说,适配器模式是指:定义一个类,将一个已经存在的类,转换成目标接口所期望的行为形式。

在具体的实现过程中,又可以基于其实现层次是类层次还是对象层次,将其分为类适配器和对象适配器。如上所写的是类适配器。

对象适配器使用组合代替继承,将源角色视为适配器角色的属性:

 class UserAdapter implements UserInterface {

     private UserInfo userInfo;

     public UserAdapter(){

     }

     public UserAdapter(UserInfo userInfo){
this.userInfo = userInfo;
} @Override
public String getName() {
return (String) userInfo.getUserBaseInfo().get("name");
} @Override
public String getTelNumber() {
return (String) userInfo.getUserBaseInfo().get("telNumber");
} }

总体而言:适配器模式是指定义一个适配器类,将一个已经存在的类,转换成目标接口所期望的行为形式。同时,一般来说,基于更多的推荐使用组合而不是继承,因此,对象适配器可能使用更多。

设计模式总结篇系列:适配器模式(Adapter)的更多相关文章

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

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

  2. 设计模式总结篇系列:原型模式(Prototype)

    首先对原型模式进行一个简单概念说明:通过一个已经存在的对象,复制出更多的具有与此对象具有相同类型的新的对象. 在理解Java原型模式之前,首先需要理解Java中的一个概念:复制/克隆. 在博文< ...

  3. 设计模式(三)-- 适配器模式(Adapter)

    适配器模式(Adapter) 考虑一个记录日志的应用,由于用户对日志记录的要求很高,使得开发人员不能简单地采用一些已有的日志工具或日志框架来满足用户的要求,而需要按照用户的要求重新开发新的日志管理系统 ...

  4. 设计模式总结篇系列:享元模式(Flyweight)

    我们都知道,Java中的String类具有如下特性:String是一个不可变类,当直通过用字符串方式使用String对象时,Jvm实际上在内存中只存有一份,且存在字符串常量池中.当对字符串直接进行修改 ...

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

    适配器模式: 将一个类的接口转换成另外一个期望的类的接口.适配器同意接口互不兼容的类一起工作. Convert the interface of a class into another interf ...

  6. 设计模式总结篇系列:抽象工厂模式(Abstract Factory)

    在上一篇的工厂方法模式中,通过一个公用的类对其他具有相同特性(实现相同接口或继承同一父类)的类的对象进行创建.随之带来的问题在于:当新定义了一个具有相同特性的类时,需要修改工厂类.这与设计模式中的开闭 ...

  7. 设计模式总结篇系列:策略模式(Strategy)

    前面的博文中分别介绍了Java设计模式中的创建型模式和结构型模式.从本文开始,将分别介绍设计模式中的第三大类,行为型模式.首先我们了解下分为此三大类的依据. 创建型模式:主要侧重于对象的创建过程: 结 ...

  8. 设计模式总结篇系列:桥接模式(Bridge)

    在实际类设计过程中,有时会遇到此类情况:由于实际的需要,某个类具有两个或两个以上的维度变化,如果利用继承将每种可能的变化情况都定义成一个类,一是会导致类膨胀的问题,二是以后不太好维护和并且违背类的设计 ...

  9. 设计模式总结篇系列:代理模式(Proxy)

    时代在发展,我们发现,现在不少明星都开始进行微访谈之类的,有越来越多的参与捐赠等.新的一天开始了,首先看下新的一天的日程安排: interface Schedule{ public void weiT ...

随机推荐

  1. Layui下拉框改变时触发事件

    layui.use(['form', 'layer'], function () { var form = layui.form(); var layer = layui.layer; form.on ...

  2. (BUG记录)记一次与其他系统交互协作时造成的锁表问题

    最近两日做公司电信某计费项目时,接收一个银行对账的任务,在完成对账后.电信和银行两方金额一致时需要进行充值.冲正操作保持金额一致.冲正服务是JAVA统一调用Tuxedo服务,这个服务已经是一个稳定可用 ...

  3. Springboot搭建SSM+JSP的web项目

    Springboot搭建SSM+JSP的web项目 一:创建项目结构: 项目结构分为三个部分: 1 后端项目开发文件: 包: Util         工具包 Mapper      db层 Serv ...

  4. 【高并发架构】Redis特点及构件模型

    数据结构 redis 相比 memcached 来说,拥有更多的数据结构,能支持更丰富的数据操作.如果需要缓存能够支持更复杂的结构和操作, redis 会是不错的选择. redis 主要有以下几种数据 ...

  5. cadence钻孔文件及光绘文件的生成

    完成PCB布线之后,需要生成钻孔文件和光绘文件交给PCB厂家制作PCB板,下面总结详细方法!

  6. Lua学习链接

    Lua捕获 Lua中_G 是个什么鬼 Lua与ObjC的交互

  7. freemarker导出带图片的word文档

    最近做一个关于文档导出功能, 顺便学习了下freemarker,做了个关于导出带图片的word文档,模板并没有写全,只是验证代码的正确性 这只是做一个小功能,故只做了后台代码关于导出的代码,并未与前台 ...

  8. rz快速上传文件到ssh服务器

    [root@k8s01 ~]# rz --helprz version 0.12.20Usage: rz [options] [filename.if.xmodem]Receive files wit ...

  9. Hello,Thread

    创建线程的三种方法,线程的生命周期,sleep,yield,join,wait 和notify,线程组,守护线程,线程的优先级 ◆ 如何创建线程 ◆ Java 中创建线程的方法有三种: 继承 Thre ...

  10. Node.js(day6)

    初始化准备工作 初始化目录 nmp init -y 安装基本的第三方插件 express npm install express --save art-template npm install art ...