设计模式笔记(7)---适配器模式(结构型)

Gof定义

将一个类的接口转换成客户所希望的另一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。

动机

在软件系统中,由于应用环境的变化,常常要将“一些现存的对象”放在心的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。

适配的意思是在不改变原有实现的基础上,将原先不兼容的接口转换为兼容的接口。在我们的生活中有着很多适配器的例子,笔记本的电源适配器、一些卡的USB读卡器等等。

在Gof23这本书中将适配器模式分成了两种:对象适配器和类适配器

对象适配器

2009-11-19_215129

上图中的Target是客户所期待的,希望去使用的类或接口。Adaptee是被适配的对象。Adapter为适配的对象。首先将上图中的结构还原成代码,如下:

/// <summary>/// 客户要使用的类/// </summary>public abstract  class Target{public abstract void Request();}/// <summary>/// 被适配的类/// </summary>public class Adaptee{public void SpecificRequest(){ }}/// <summary>/// 适配对象/// </summary>public class Adapter : Target{private Adaptee adapee = new Adaptee();public void Request(){adapee.SpecificRequest();}}/// <summary>/// 客户程序/// </summary>public class App{static void Main(string[] args){Target target = new Adapter();//对客户来说是调用的Request,实际上是调用的SpecificRequesttarget.Request();}}

接着根据上面的思路来看一个实际例子,我们要来实现一个对栈的操作,有一个IStact接口,里面有三个方法Push(进栈)、Pop(出栈)和GetTopItem(取最顶层元素),这个IStact接口将相当于上面的Target,想要实现进栈出栈的操作,如果自己去实现数据结构显得比较麻烦,在此可以将net提供的ArrayList类拿来一用,ArrayList类就是被适配的对象,相当于上面的Adaptee。在写一个适配类StactAdapter类完成功能就可以了。

/// <summary>
/// 栈的接口
/// </summary>
public interface IStack
{void Push(object item);void Pop();Object GetTopItem();
}
/// <summary>
/// 对象适配器
/// </summary>
public class StactAdapter:IStack
{ArrayList list;/// <summary>/// 构造函数中实例化ArrayList/// </summary>public StactAdapter(){list = new ArrayList();}/// <summary>/// 进栈/// </summary>/// <param name="item">压入栈的元素</param>public void Push(object item){list.Add(item);}/// <summary>/// 出栈/// </summary>public void Pop(){list.RemoveAt(list.Count - 1);}/// <summary>/// 取最顶层的元素/// </summary>/// <returns></returns>public Object GetTopItem(){return list[list.Count - 1];}
}
/// <summary>
/// 客户调用
/// </summary>
public class App
{static void Main(string[] args){IStack myStack = new StactAdapter();myStack.Push("oec2003");myStack.Push("oec2004");myStack.Push("oec2005");myStack.Pop();Console.WriteLine(myStack.GetTopItem());}
}

Adapter模式理解起来也非常简单,IStact中的Push和Pop方法就是添加元素和移除元素的功能,正好系统类ArrayList中就提供了Add和RemoveAt这样的方法,所以就可以拿来借用,通过适配器类(StactAdapter)的转换使得Push和Pop方法可以支持添加和移除元素的功能,就像我们经常使用的笔记本一样,本来现实中的电压和笔记本所需要的电压不相符,通过电源适配器的转换就将现实中的电压转换成笔记本所需要的电压。

类适配器

2009-11-19_215214

类适配器中使用到了剁成继承,从图中可以看出Adapter继承了Target和Adaptee,而在C#语言中不支持多继承,如果一定要在C#中使用类适配器,那么Target和Adapter其中之一一定要为接口,这样就有了一定的局限性。再者Adapter继承了Target和Adapter后就拥有了这两个的职责,这也违反了单一职责原则,所以通常我们使用对象适配器,下面还是给出配合上图的代码,Target设计成了接口。

/// <summary>
/// 客户要使用的类
/// </summary>
public interface ITarget
{public void Request();
}
/// <summary>
/// 被适配的类
/// </summary>
public class Adaptee
{public void SpecificRequest(){}
}
/// <summary>
/// 适配对象
/// </summary>
public class Adapter : Adaptee,ITarget
{public void Request(){this.SpecificRequest();}
}
/// <summary>
/// 客户程序
/// </summary>
public class App
{static void Main(string[] args){ITarget target = new Adapter();//对客户来说是调用的Request,实际上是调用的SpecificRequesttarget.Request();}
}

Adapter模式的几个要点

Adapter模式主要英语于“希望复用一些现存的类,但是接口又与复用环境要求不一致的情况”,在遗留代码复用、类库迁移方面非常有用。

Gof23定义了两种Adapter模式的实现结构:对象适配器和类适配器。但类适配器采用“多继承”的实现方式,带来了不良的高耦合,所以一般不推荐使用。对象适配器采用“对象组合”的方式,更符合松耦合。

Adapter模式可以实现的非常灵活,不必拘泥于Gof23中定义的两种结构。例如,完全可以讲Adapter模式中的“现存对象”作为新的接口方法参数,来达到适配的目的。

Adapter模式本身要求我们尽可能地使用“面向接口的编程”风格,这样才能在后期方便适配。

 

 

作者:oec2003(水杯)
出处:http://oec2003.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/abenmao/archive/2012/05/25/2517989.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/401545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件设计模式之适配器模式(JAVA)

什么是适配器模式&#xff1f; 在计算机编程中&#xff0c;适配器模式&#xff08;有时候也称包装样式或者包装&#xff09;将一个类的接口适配成用户所期待的。适配器能将因为接口不兼容而不能在一起工作的类工作在一起&#xff0c;做法是将类自己的接口包裹在一个已存在的类中…

Javascript 调试技巧

Javascript 调试技巧 在代码中寻找错误 1&#xff09;alert 方法&#xff1a; 弹框提示 2&#xff09;console 方法 在调试窗口上打印 JavaScript 值 3&#xff09;断点调试 在浏览器开发者工具中为JS代码添加断点&#xff0c;让JS执行到某一特定位置停住&#xff0c;方便…

WPF程序将DLL嵌入到EXE的两种方法

2019独角兽企业重金招聘Python工程师标准>>> WPF程序将DLL嵌入到EXE的两种方法 这一篇可以看作是《Visual Studio 版本转换工具WPF版开源了》的续&#xff0c;关于《Visual Studio 版本转换工具WPF版开源了》可以参看地下地址&#xff08;两篇是一样的&#xff09;&…

华中地区高校第七届ACM程序设计大赛——之字形矩阵【2012年5月27日】

题意&#xff1a;输入a b Right 或 a b Down ,根据输入输出之字形路径的矩阵。 1 #include <stdio.h>2 int xx[4]{0,1,-1,1},yy[4]{1,0,1,-1};3 int map[100][100],col,row,x,y,dir,steps,idx;4 char sel[10];5 void nextdir()6 {7 switch(dir)8 {9 case 0: …

oracle文件

1、控制文件和日志文件 控制文件&#xff08;Control File&#xff09;是一个很小的二进制文件&#xff0c;用于描述和维护数据库的物理结构。在Oracle数据库中&#xff0c;控制文件相当重要&#xff0c;它存放有数据库中数据文件和日志文件的信息。Oracle数据库在启动时需要访…

常用命令-tar 加密

2019独角兽企业重金招聘Python工程师标准>>> 在当前目录下有一个pma目录的文件夹: 1、使用tar对文件压缩加密&#xff1a; # tar -zcvf - pma|openssl des3 -salt -k password | dd ofpma.des3 完成将得到一个pma.des3的打包文件&#xff0c;用你设置的密码替换pas…

ORM SQLAlchemy 简介

对象关系映射&#xff08;Object Relational Mapping&#xff0c;简称ORM使用DB-API访问数据库&#xff0c;需要懂 SQL 语言&#xff0c;能够写 SQL 语句&#xff0c;如果不想懂 SQL&#xff0c;又想使用关系型数据库&#xff0c;可以使用 ORM,一个 ORM , 它的一端连着 Databas…

转:OAUTH协议简介

OAUTH协议简介 原文链接 摘要&#xff1a;OAUTH协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第 三方触及到用户的帐号信息&#xff08;如用户名与密码&#xff09;&#xff0c;即第三方无需使用用户的用户名与密…

java集合框架05——ArrayList和LinkedList的区别

前面已经学习完了List部分的源码&#xff0c;主要是ArrayList和LinkedList两部分内容&#xff0c;这一节主要总结下List部分的内容。 List概括 先来回顾一下List在Collection中的的框架图&#xff1a; 从图中我们可以看出&#xff1a; 1. List是一个接口&#xff0c;它继承与Co…

Javascript 函数详解

Javascript 函数详解 1&#xff09;函数声明&#xff1a; 通过关键字function定义&#xff0c;把函数作为变量来声明 函数声明后不会立即执行&#xff0c;会在我们需要的时候调用到。 <script>function myFunction(a, b) {return a * b;}// js对大小写敏感&#xff0c;…

ln链接使用

首先说明下Linux下删除、移动、复制的意义。删除:是将inode表放回空闲区由1变为0&#xff0c;还可以找回文件移动:是将inode表不变&#xff0c;将文件转移至对应条目&#xff0c;删除原条录。同分区上操作速度快&#xff0c;不同分区相当于创建、删除原文件复制:是重建inode表&…

Javascript 对象一(对象详解)

JS创建对象的几种方法1. Object 构造函数 创建 2. 对象字面量表示法 创建 3. 使用工厂模式创建对象 在 Car 函数中&#xff0c;返回的是一个对象。那么我们就无法判断返回的对象究竟是一个什么样的类型。于是就出现了第四种创建对象的模式 4. 使用构造函数创建对象 构造函数…

Delphi工具之Image Editor

Delphi Image Editor是一个工具&#xff0c;可用它来创建并编辑位图&#xff08;.bmp&#xff09;、图标&#xff08;.ico&#xff09;和光标&#xff08;.cur&#xff09;&#xff0c;还可以用它创建资源工程&#xff0c;将多个位图、图标和光标包含到单个资源文件&#xff08…

小程序 获取当前用户城市信息(省市区)

步骤使用 wx.getLocation来获取位置授权&#xff1a;获取到设备当前的地理位置信息&#xff0c;这个信息是当前位置的经纬度使用其他第三方地图服务的API&#xff1a;获取当前位置是处于哪个国家&#xff0c;哪个城市等信息&#xff08;eg&#xff1a;腾讯地图、百度地图&#…

小程序 获取当前用户地址及地图显示

步骤使用 wx.getLocation来获取当前位置&#xff1a; 注意;当用户取消位置获取授权之后,再次点击获取位子按钮小程序不会再提醒用户是否授权,这个时候最好自己弹出提示框让用户去设置页面开启授权设置. wx.getLocation({type: wgs84, //wgs返回 gps坐标&#xff0c; gcj02返回…

CSS3 box-shadow 属性

2019独角兽企业重金招聘Python工程师标准>>> 实例 向 div 元素添加 box-shadow&#xff1a; div { box-shadow: 10px 10px 5px #888888; } 亲自试一试 <!DOCTYPE html> <html> <head> <style> div { width:300px; height:100px; backgroun…

[译]Kinect for Windows SDK开发入门(二):基础知识 上

上篇文章介绍了Kinect开发的环境配置&#xff0c;这篇文章和下一篇文章将介绍Kinect开发的基本知识&#xff0c;为深入研究Kinect for Windows SDK做好基础。 每一个Kinect应用都有一些基本元素。应用程序必须探测和发现链接到设备上的Kinect传感器。在使用这些传感器之前&…

小程序 开发经验

项目目录理解components自定义组件库config一个公用的数据配置images本地、上传的图片放置pagespages目录存储小程序的每个页面&#xff0c;每个页面包含四个文档.json为配置文件.wxml 为模板文件&#xff0c;相当于HTML模板.wxss 为样式文件&#xff0c;相当于HTML的CSS样式表…

EasyUI,二级页面内容的操作

2019独角兽企业重金招聘Python工程师标准>>> 父页面获取子页面的数据 1.若仅仅是勾选&#xff0c;则将勾选的放到map中(key&#xff0c;value)&#xff0c;key是能验证数据唯一的字段&#xff0c;value就是勾选行的rowData&#xff1b; 再将map转换成json格式的字…

Javascript 对象二(Number、String、Boolean、Array、Date、Math、RegExp)

Javascript 对象二&#xff08;Number、String、Boolean、Array、Date、Math、RegExp&#xff09;Number 数字 对象String 字符串 对象Boolean 布尔 对象Array 数组 对象Date 日期 对象Math 算数 对象RegExp 正则表达式 对象Number 数字 对象 JavaScript中 数字不分为整数类型…