定义

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

类适配器模式

使用继承的方式实现没有提供的接口从而达到适配到新系统的需求。

对象适配器模式

使用聚合的方式提供新系统需要的所有接口。

UML

优点

  1. 更好的复用性:系统需要使用现有的类,而此类的接口不符合系统的需要。那么通过适配器模式就可以让这些功能得到更好的复用。
  2. 更好的扩展性:在实现适配器功能的时候,可以调用自己开发的功能,从而自然地扩展系统的功能。
  3. 将目标类和适配者类解耦。
  4. 增加了类的透明性和复用性,将具体的实现封装在适配者类中,对于客户端类来说是透明的,而且提高了适配者的复用性。
  5. 灵活性和扩展性都非常好,符合开闭原则。

缺点

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

应用场景

  1. 想使用一个已经存在的类,但如果它的接口和你的要求不相同时。可以使用适配器模式。两个类所做的事情相同或相似,但接口不同时可以使用。

经典例子

里皮翻译用汉语布置恒大队员战术。球员都继承于中国人,都会说汉语,而里皮并不会说汉语。在不知战术的时候,我们需要给里皮一个翻译,这个翻译就是里皮的适配器。翻译可以和球员一样,也继承于中国人,也有说汉语这个方法。而翻译认识里皮,翻译在说汉语()这个方法的时候,实际上是在说里面用意大利语的内容。

示例

使用适配器模式适配新的员工信息。

Java

  1. public class Main
  2. {
  3. public static void main(String[] args)
  4. {
  5. //类适配器模式使用
  6. IMSEmployeeInfo info = new MSEmployeeInfo1();
  7. System.out.println(info.nickname());
  8.  
  9. //对象适配器模式使用
  10. IEmployeeInfo info2 = new EmployeeInfo();
  11. IMSEmployeeInfo info3 = new MSEmployeeInfo2(info2);
  12. System.out.println(info3.nickname());
  13. }
  14.  
  15. /**
  16. * 员工信息接口
  17. */
  18. public static interface IEmployeeInfo
  19. {
  20. /**
  21. * 工号
  22. */
  23. int id();
  24.  
  25. /**
  26. * 姓名
  27. */
  28. String name();
  29. }
  30.  
  31. /**
  32. * 员工信息类
  33. */
  34. public static class EmployeeInfo implements IEmployeeInfo
  35. {
  36. @Override
  37. public int id() {
  38. return 250;
  39. }
  40.  
  41. @Override
  42. public String name() {
  43. return "李二狗";
  44. }
  45. }
  46.  
  47. /**
  48. * 需要接入的MS公司员工信息接口
  49. */
  50. public static interface IMSEmployeeInfo
  51. {
  52. /**
  53. * 工号
  54. */
  55. int id();
  56.  
  57. /**
  58. * MS公司不使用人物的真名, 而是给员工取了一个英文名
  59. */
  60. String nickname();
  61. }
  62.  
  63. /**
  64. * 类适配器模式的实现
  65. */
  66. public static class MSEmployeeInfo1 extends EmployeeInfo implements IMSEmployeeInfo
  67. {
  68. @Override
  69. public String nickname() {
  70. //这里通过查询得到了李二狗的英文名并返回
  71. return "尼古拉斯";
  72. }
  73. }
  74.  
  75. /**
  76. * 对象适配器模式的实现
  77. */
  78. public static class MSEmployeeInfo2 implements IMSEmployeeInfo
  79. {
  80. private IEmployeeInfo _info;
  81.  
  82. public MSEmployeeInfo2(IEmployeeInfo info)
  83. {
  84. _info = info;
  85. }
  86.  
  87. @Override
  88. public int id() {
  89. return _info.id();
  90. }
  91.  
  92. @Override
  93. public String nickname() {
  94. //这里通过查询得到了李二狗的英文名并返回
  95. return "尼古拉斯";
  96. }
  97. }
  98. }

结构类模式(一):适配器(Adapter)的更多相关文章

  1. 设计模式之结构类模式大PK

                                      结构类模式大PK 结构类模式包括适配器模式.桥梁模式.组合模式.装饰模式.门面模式.享元模式和代理模式.之所以称其为结构类模式,是因 ...

  2. 设计模式之结构类模式PK

    结构类模式包括: 适配器模式 桥梁模式 组合模式 装饰模式 门面模式 享元模式 代理模式 结构类模式着重于如何建立一个软件结构 为什么叫结构类模式呢? 因为他们都是通过组合类或对象产生更大结构以适应更 ...

  3. 【原】模式之-适配器Adapter模式

    适配器Adapter模式 适配器模式(Adapter Pattern)把一个类的接口变换成客户端所期待的的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作. 模式所涉及的角色有 ...

  4. 漫谈设计模式(一):代理(Proxy)模式与适配器(Adapter)模式对比

    1.前言 为什么要将代理模式与适配器模式放在一起来说呢?因为它们有许多的共同点,当然也有一些不同的地方.首先两者都是属于结构型模式.结构型模型是这样定义的: 结构型模式涉及到如何组合类和类以获得更大的 ...

  5. 结构类模式(四):装饰(Decorator)

    定义 动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 它是通过创建一个包装对象,也就是装饰来包裹真实的对象. 特点 装饰对象和真实对象有相同的接口.这样客户端对象就能以 ...

  6. 结构类模式(三):组合(Composite)

    定义 将对象组合成树形结构以表示“部分整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客 ...

  7. 结构类模式(七):代理(Proxy)

    定义 为其他对象提供一种代理以控制对这个对象的访问. 代理模式也叫做委托模式,它是一项基本设计技巧.许多其他的模式,如状态模式.策略模式.访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应 ...

  8. 结构类模式(六):享元(Flyweight)

    定义 运用共享技术有效的支持大量细粒度的对象. 两个状态 内蕴状态存储在享元内部,不会随环境的改变而有所不同,是可以共享的. 外蕴状态是不可以共享的,它随环境的改变而改变的,因此外蕴状态是由客户端来保 ...

  9. 结构类模式(五):外观(Facade)

    定义 为子系统中的一组接口提供一个一致的界面,定义一个高层接口,这个接口使得这一子系统更加容易使用. UML 优点 对客户屏蔽了其子系统组件,因而减少了客户处理对象的数目,并使得子系统实用起来更方便. ...

随机推荐

  1. php 格式化数字 位数不足前面加0补足

    本文引用自 http://www.fengfly.com/plus/view-62827-1.html 补0: <?php $var = sprintf("%03d", 12 ...

  2. JNDI绑定数据库

    经过3个多小时的努力,配置JNDI数据源(主要是通过DBCP连接池)终于搞定- 还是Tomcat官方的说明好,不过全是英文的,大概还看得懂. 百度上那么花花绿绿的太多了,一个也没成功!... 本例使用 ...

  3. Python定时调度--多任务同一时间开始跑 scheduler.enterabs

    Event Priorities If more than one event is scheduled for the same time their priority values are use ...

  4. 【转】Undefined symbols for architecture i386:和"_OBJC_CLASS_$_xx", referenced from:问题解决方法

    多个人共同操作同一个项目或拷贝项目时,经常会出现类似这样的问题: Undefined symbols for architecture i386: "_OBJC_CLASS_$_xx文件名& ...

  5. MySQL基础之第14章 存储过程和函数

    避免编写重复的语句 安全性可控 执行效率高 14.1.创建存储过程和函数 14.1.1.创建存储过程 CREATE PROCEDUREsp_name ([proc_parameter[,...]]) ...

  6. Javascript判断是否是ipad的浏览器

    ipad用的是Safari Mobile浏览器,访问的UA为: Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/5 ...

  7. 基数排序/Go实现

    package main import ( "fmt" ) type Radix struct { length int //序列中最大数的位数 radix [][]int //0 ...

  8. SVN中检出(check out) 和 导出(export) 的区别

    SVN是常用的一种常见的版本控制软件.SVN中检出(check out) 和 导出(export) 的区别主要有如下几条: check out跟check in对应,export跟import对应. ...

  9. Android FrameWork——相关内容

    http://blog.csdn.net/stonecao/article/category/781516

  10. 自定义View绘制字符串

    import android.app.Activity; import android.os.Bundle; import android.view.Display; import android.v ...