适配器模式 《转》

现实生活中的适配器

本文讨论适配器模式。适配器模式是23中设计模式之一,它的主要作用是在新接口和老接口之间进行适配。它非常像我们出国旅行时带的电源转换器。为了举这个例子,我还特意去京东上搜了一下电源转换器,确实看到了很多地方的标准不一样。我们国家的电器使用普通的扁平两项或三项插头,而去外国的话,使用的标准就不一样了,比如德国,使用的是德国标准,是两项圆头的插头。如果去德国旅游,那么我们使用的手机充电器插头无法插到德国的插排中去,那就意味着我们无法给手机充电。怎样解决这个问题呢?只要使用一个电源转化器就行了。如下图所示:

该适配器下面的插头符合德国标准,可以插到德国的插排中去,上面提供的接口符合国标,可以供我们的手机充电器使用。

实现电源适配器

下面我们使用代码来表述适配器模式:

代码中有两个接口,分别为德标接口和国标接口,分别命名为DBSocketInterface和GBSocketInterface,此外还有两个实现类,分别为德国插座和中国插座,分别为DBSocket和GBSocket。为了提供两套接口之间的适配,我们提供了一个适配器,叫做SocketAdapter。除此之外,还有一个客户端,比如是我们去德国旅游时住的一家宾馆,叫Hotel,在这个德国旅馆中使用德国接口。

德标接口:

[java] view plain copy

  1. /**
  2. * 德标接口
  3. */
  4. public interface DBSocketInterface {
  5. /**
  6. * 这个方法的名字叫做:使用两项圆头的插口供电
  7. * 本人英语就这个水平
  8. */
  9. void powerWithTwoRound();
  10. }

德国插座实现德标接口

[java] view plain copy

  1. /**
  2. * 德国插座
  3. */
  4. public class DBSocket implements DBSocketInterface{
  5. public void powerWithTwoRound(){
  6. System.out.println("使用两项圆头的插孔供电");
  7. }
  8. }

德国旅馆是一个客户端,它里面有德标的接口,可以使用这个德标接口给手机充电:

[java] view plain copy

  1. /**
  2. * 德国宾馆
  3. */
  4. public class Hotel {
  5. //旅馆中有一个德标的插口
  6. private DBSocketInterface dbSocket;
  7. public Hotel(){}
  8. public Hotel(DBSocketInterface dbSocket) {
  9. this.dbSocket = dbSocket;
  10. }
  11. public void setSocket (DBSocketInterface dbSocket){
  12. this.dbSocket = dbSocket;
  13. }
  14. //旅馆中有一个充电的功能
  15. public void charge(){
  16. //使用德标插口充电
  17. dbSocket.powerWithTwoRound();
  18. }
  19. }

现在写一段代码进行测试:

[java] view plain copy

  1. public class Test {
  2. public static void main(String[] args) {
  3. //初始化一个德国插座对象, 用一个德标接口引用它
  4. DBSocketInterface dbSoket = new DBSocket();
  5. //创建一个旅馆对象
  6. Hotel hotel = new Hotel(dbSoket);
  7. //在旅馆中给手机充电
  8. hotel.charge();
  9. }
  10. }

运行程序,打印出以下结果: 使用两项圆头的插孔供电

现在我去德国旅游,带去的三项扁头的手机充电器。如果没有带电源适配器,我是不能充电的,因为不可能为了我一个旅客而为我更改墙上的插座,更不可能为我专门盖一座使用中国国标插座的宾馆。因为人家德国人一直这么使用,并且用的挺好,俗话说入乡随俗,我就要自己想办法来解决问题。对应到我们的代码中,也就是说,上面的Hotel类,DBSocket类,DBSocketInterface接口都是不可变的(由德国的客户提供),如果我想使用这一套API,那么只能自己写代码解决。

下面是国标接口和中国插座的代码。

国标接口:

[java] view plain copy

  1. /**
  2. * 国标接口
  3. */
  4. public interface GBSocketInterface {
  5. /**
  6. * 这个方法的名字叫做:使用三项扁头的插口供电
  7. * 本人英语就这个水平,从有道词典查得, flat意思好像是: 扁的
  8. */
  9. void powerWithThreeFlat();
  10. }

中国插座实现国标接口:

[java] view plain copy

  1. /**
  2. * 中国插座
  3. */
  4. public class GBSocket implements GBSocketInterface{
  5. @Override
  6. public void powerWithThreeFlat() {
  7. System.out.println("使用三项扁头插孔供电");
  8. }
  9. }

可以认为这两个东西是我带到德国去的,目前他们还不能使用,因为接口不一样。那么我必须创建一个适配器,这个适配器必须满足以下条件:

1    必须符合德国标准的接口,否则的话还是没办法插到德国插座中;

2    在调用上面实现的德标接口进行充电时,提供一种机制,将这个调用转到对国标接口的调用 。

这就要求:

1 适配器必须实现原有的旧的接口

2 适配器对象中持有对新接口的引用,当调用旧接口时,将这个调用委托给实现新接口的对象来处理,也就是在适配器对象中组合一个新接口。

下面给出适配器类的实现:

[java] view plain copy

  1. public class SocketAdapter
  2. implements DBSocketInterface{   //实现旧接口
  3. //组合新接口
  4. private GBSocketInterface gbSocket;
  5. /**
  6. * 在创建适配器对象时,必须传入一个新街口的实现类
  7. * @param gbSocket
  8. */
  9. public SocketAdapter(GBSocketInterface gbSocket) {
  10. this.gbSocket = gbSocket;
  11. }
  12. /**
  13. * 将对就接口的调用适配到新接口
  14. */
  15. @Override
  16. public void powerWithTwoRound() {
  17. gbSocket.powerWithThreeFlat();
  18. }
  19. }

这个适配器类满足了上面的两个要求。下面写一段测试代码来验证一下适配器能不能工作,我们按步骤一步步的写出代码,以清楚的说明适配器是如何使用的。

1    我去德国旅游,带去的充电器是国标的(可以将这里的GBSocket看成是充电器)

[java] view plain copy

  1. GBSocketInterface gbSocket = new GBSocket();

2    来到德国后, 找到一家德国宾馆住下 (这个宾馆还是上面代码中的宾馆,使用的依然是德国标准的插口)

[java] view plain copy

  1. Hotel hotel = new Hotel();

3    由于没法充电,我拿出随身带去的适配器,并且将我带来的充电器插在适配器的上端插孔中。这个上端插孔是符合国标的,我的充电器完全可以插进去。

[java] view plain copy

  1. SocketAdapter socketAdapter = new SocketAdapter(gbSocket);

4     再将适配器的下端插入宾馆里的插座上

[java] view plain copy

  1. hotel.setSocket(socketAdapter);

5    可以在宾馆中使用适配器进行充电了

[java] view plain copy

  1. hotel.charge();

上面的五个步骤就是适配器的使用过程,下面是完整的测试代码。

[java] view plain copy

  1. public class TestAdapter {
  2. public static void main(String[] args) {
  3. GBSocketInterface gbSocket = new GBSocket();
  4. Hotel hotel = new Hotel();
  5. SocketAdapter socketAdapter = new SocketAdapter(gbSocket);
  6. hotel.setSocket(socketAdapter);
  7. hotel.charge();
  8. }
  9. }

运行上面的程序,打印出以下结果:

使用三项扁头插孔供电

这说明适配器起作用了,上一个实例中打印的是:使用两项圆头的插孔供电。 现在可以使用三项扁头插孔供电了。我们并没有改变宾馆中的德标插口,提供了一个适配器就能使用国标的插口充电。这就是适配器模式的魅力:不改变原有接口,却还能使用新接口的功能。

由于上面的代码都是分片的,没有完整的项目源码,为了使读者对示例中的类和接口更清晰,下面给出UML类图:

总结

根据上面的示例,想必读者应该能比较深入的了解到了适配器模式的魔力。下面给出适配器模式的定义(该定义来自于《Head First 设计模式》):

适配器模式将一个类的接口转换成客户期望的另一个接口,让原本不兼容的接口可以合作无间。

下面给出适配器模式的类图(该类图同样来自于《Head First 设计模式》):

适配器模式的三个特点:

1    适配器对象实现原有接口

2    适配器对象组合一个实现新接口的对象(这个对象也可以不实现一个接口,只是一个单纯的对象)

3    对适配器原有接口方法的调用被委托给新接口的实例的特定方法

有人认为讲解设计模式的例子都太简单,看着感觉是那么回事,但是要是真想在项目开发中使用,还真是应用不到。其实我们不必在项目中刻意使用设计模式,而是应该从实际的设计问题出发,看哪个模式能解决我们的问题,就使用哪个模式。不要为了使用模式而使用模式,那样就舍本逐末了,一般情况下,只要遵循一定的设计原则就可以了,设计模式也是根据这些原则被总结出来的,熟悉了这些原则,模式自然而然就有了。

时间: 2024-07-29 09:39:49

适配器模式 《转》的相关文章

Happy 设计模式之适配器模式(JAVA)

设计模式-适配器模式 适配器模式定义 适配器模式,将一个类的的接口转换成客户或者产品希望的接口形式,就是原本不兼容或者甚至不相干的接口不能一起工作的接口一起工作,完成需求或者客户的需求. 适配器模式的使用场景 1.当你使用一个已经存在的类,而他的接口不符合你的需求. 2.你想要创建一个复用的类,该类可以与其相关的类或者不可见的类协同工作. 适配器角色 Target:目标接口 TargetImpl:目标实现类 Adapter:适配器 Adaptee:被适配者 代码解析: package com.d

Javascript设计模式理论与实战:适配器模式

有的时候在开发过程中,我们会发现,客户端需要的接口和提供的接口发生不兼容的问题.由于特殊的原因我们无法修改客户端接口.在这种情况下,我们需要适配现有接口和不兼容的类,这就要提到适配器模式.通过适配器,我们可以在不用修改旧代码的情况下也能使用它们,这就是适配器的能力. 基本理论 适配器模式:将一个接口转换成客户端需要的接口而不需要去修改客户端代码,使得不兼容的代码可以一起工作. 适配器主要有3个角色组成:(1)客户端:调用接口的类(2)适配器:用来连接客户端接口和提供服务的接口的类(3)适配者:提

适配器模式开发

Adapter模式也叫适配器模式,是构造型模式之一,通过Adapter模式可以改变已有类(或外部类)的接口形式. 在大规模的系统开发过程中,我们常常碰到诸如以下这些情况:我们需要实现某些功能,这些功能已有还不太成熟的一个或多个外部组件, 如果我们自己重新开发这些功能会花费大量时间:所以很多情况下会选择先暂时使用外部组件, 以后再考虑随时替换.避免代码大面积修改Adapter模式就是针对这种类似需求而提出来的.Adapter模式通过定义一个新的接口(对要实现功能加以抽象),和一个实现该接口的Ada

7 结构型模式-----适配器模式

模式动机:有时软件复用的一个难题就是接口的不兼容性,适配器的职责就是为客户提供兼容的适配者接口,使得客户只需访问一类接口就可以调用合适的适配者,而其中的适配细节则有适配器来完成. 模式定义(Adapter Pattern):将一个接口转换为用户期望的接口,使得那些接口不兼容的类可以一起工作. 模式结构图: 模式代码: bt_适配器模式.h: 1 #ifndef AP_H 2 #define AP_H 3 #include <iostream> 4 5 using namespace std;

适配器模式(Adapter)

1.定义: 适配器模式是将一个类的接口转换成客户端希望的另一个接口,适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 结构与说明: Client:客户端,调用自己需要的领域接口Target. Target:定义客户端需要的跟特定领域相关的接口. Adaptee:已经存在的接口,但与客户端需要的特定领域接口不一致,需要被适配. Adapter:适配器,把Adaptee适配成Client需要的Target. 2.代码示例 (1)已经存在的应用接口,需要被适配的类Adaptee 1

设计模式【适配器模式】

适配器模式的核心思想:把原有的接口转换成调用者所期望的接口,从而使不同接口的类可以一起工作. 在此,需要介绍适配器中包含的3个角色: ■源角色Adaptee:需要适配的目标或接口. ■目标角色Target:所期望得到的接口. ■适配器角色Adapter:适配类是本模式的核心,用来把源接口转换成目标接口,显然这三者的相互关系组成了适配器模式的原型. [转载使用,请注明出处:http://blog.csdn.net/mahoking] 适配器模式也叫做包装器模式(Wrapper),根据适配器对象的不

Java模式(适配器模式)

今天看了下Java中的适配器模式,下面就来小做下总结和谈谈感想,以便日后使用. 首先,先来先讲讲适配器.适配就是由“源”到“目标”的适配,而其中链接两者的关系就是适配器.它负责把“源”过度到“目标”.举个简单的样例,比方有一个“源”是一个对象人,他拥有2种技能各自是说日语和说英语,而某个岗位(目标)须要你同一时候回说日语.英语.和法语,好了,如今我们的任务就是要将人这个“源”适配的这个岗位中,怎样适配呢?显而易见地我们须要为人加入一个说法语的方法,这样才干满足目标的须要. 接着讨论怎样加说法语这

【结构型模式】《大话设计模式》——读后感 (12)在NBA我需要翻译?——适配器模式

适配器模式:将一个类的接口转换成客户希望的另外一个接口,Adapter模式使得原本由于接口不兼容而不能在一起工作的 那些类可以在一起工作了[DP] UML类图: 简单模拟一下代码: //已存在的.具有特殊功能.但不符合我们既有的标准接口的类 package com.sjmx.adapter; //已存在的.具有特殊功能.但不符合我们既有的标准接口的类 public class Adaptee { public void specificRequest() { System.out.println

设计模式之四:适配器模式(Adapter Pattern)

在软件系统中,由于应用环境的变化,常常需要将"一些现存的对象"放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的.如果能既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?这就是适配器模式要解决的问题. 目的:将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 下面以日志记录程序为例子说明Adapter模式.假设我们在软件开发中要记录日志,包括数据库记录日志DatabaseLog和文本文件

设计模式之适配器模式与外观模式

适配器模式将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 例子:火鸡变鸭子. 先定义一个鸭子接口. package cn.sp.test06; /** * 鸭子 * @author 2YSP * */ public interface Duck { //具备呱呱叫 和 飞行的能力 public void quack(); public void fly(); } package cn.sp.test06; /** * 绿头鸭是鸭子的子类 * @author