设计模式之适配器模式

来源:互联网 发布:oracle 删除数据库 编辑:程序博客网 时间:2024/05/20 23:31

一、简介

适配器模式(Adapter Pattern)也称为变压器模式:将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。

  适配器模式是一种补救模式,而不是为了解决还处在开发阶段的问题,而是解决正在服役的项目问题,所以在详细设计阶段无需考虑它,当然这个模式使用的主要场景是扩展应用中,是为了减少代码修改所带来的风险。

注意:使用适配器模式一定要遵守依赖倒置原则和里氏替换原则,否则即使在适合使用适配器的场合下,也会带来非常大的改造。

简单理解:就是将变化后的实现封装到原有的接口的一个实现方法中去,从而原有的类通过原有接口的约束就可以实现变化后的代码了。(当然不一定都是接口)

适配器模式的三个角色:

  1. Target目标角色,该角色定义了其遵循的接口。
  2. Adaptee源角色,源角色就是你想要将其改变目标角色。
  3. Adapter适配器角色,把源角色转换为目标角色,其方式是通过集成或是类关联的方式。

适配器模式的优点:

  • 适配器模式可以让两个没有任何关系的类在一起运行,只要适配器这个角色能够搞定他们就成;
  • 增加了类的透明性;我们访问的目标角色,但是具体的实现都委托给了源角色,而这些对高层次模块是透明地,也是它不需要关心的。
  • 提高了类的复用度;源角色在原有的系统中还是可以正常使用,而在目标角色中也可以充当新的身份。
  • 灵活性非常好;哪天不想用了直接将适配器删除,不影响任何代码。

适配器模式使用场景:

  你有动机修改一个已经投产中的接口时,适配器模式可能是最适合你的模式。

二、详解

1. 接口适配


  上面是一个简单的UML模型,其中RequiredInterface接口声明了Client(客户端)所要调用的requiredMethod()方法。在ExistingClass中定义了usefulMethod()方法,这个方法Client类需要的实现。因此需要对ExistingClass类进行适配,来满足客户端对象的需求,这时我们编写一个集成自ExistingClass的Adapter并同时实现了RequiredInterface接口的类,通过重写requiredMethod()方法将客户端的请求委派到usefulMethod()方法。Adapter就是一个适配器,他的功能是将ExistingClass包装成一个符合RequiredInterface接口的实现类。

接口RequiredInterface :

/** * 定义了客户端需要调用的方法 *  * @author fxb * */public interface RequiredInterface {public void requiredMethod();}
客户端Client :(目标角色)

public class Client implements RequiredInterface{@Overridepublic void requiredMethod() {System.out.println("客户端原来实现的代码。。。。。");}}
源角色ExistingClass :
public class ExistingClass {public void usefulMethod(){System.out.println("更佳的实现方法。。。。。");}}
适配器角色Adapter :

public class Adapter extends ExistingClass implements RequiredInterface{@Overridepublic void requiredMethod() {usefulMethod();}}
测试场景:

public class Ceshi {public static void main(String[] args) {RequiredInterface temp=new Client();temp.requiredMethod();System.out.println("---------分割线---------");RequiredInterface tempOfAdapter=new Adapter();tempOfAdapter.requiredMethod();}}
运行结果为:

客户端原来实现的代码。。。。。---------分割线---------更佳的实现方法。。。。。
  当客户端在接口重定义了它所期待的行为时,就可以运用适配器模式,提供一个实现该接口的类,并同时令其成为现有类的接口。倘若没有定义客户端期待的接口,也可以运用适配器模式,但必须使用“对象适配器”。

2. 类与接口适配器


  这种结构显然使用接口适配是不可能的,这个例子中假设RequiredClass是一个抽象类(当然也没必要是抽象类),我们根据上面示例的思路我们仍然建立了一个适配器Adapter,这个适配器继承了RequiredClass这个抽象类,我们通过适配器可以将ExistingClass类适配为符合客户端的需求。

抽象类:

public abstract class RequiredInterface {public abstract void requiredMethod();}
客户端:

public class Client extends RequiredInterface{@Overridepublic void requiredMethod() {System.out.println("客户端原来实现的代码。。。。。");}}
源目标:
public class ExistingClass {public void usefulMethod(){System.out.println("更佳的实现方法。。。。。");}}
适配器:

public class Adapter extends RequiredInterface{private ExistingClass outInterface=new ExistingClass();@Overridepublic void requiredMethod() {outInterface.usefulMethod();}}
测试场景:

public class Ceshi {public static void main(String[] args) {RequiredInterface temp=new Client();temp.requiredMethod();System.out.println("---------分割线---------");RequiredInterface tempOfAdapter=new Adapter();tempOfAdapter.requiredMethod();}}
运行结果:

客户端原来实现的代码。。。。。---------分割线---------更佳的实现方法。。。。。

三、总结

  适配器模式使我们可以重用一个现有的类,以满足客户端的需求。当客户端通过接口表达其需求时,通常可以创建一个实现了该接口的心累,同时使该类继承自现有类。这种方式能够将客户端的调用转换为对现有方法的调用。

  当客户端没有指定它所需要的接口时,我们需要创建一个新的客户端子类,他将使用现有类(源角色)的实例。这种 方式将客户端的调用指向现有类的实例。如果我们不需要(或许不能)重写客户端调用的方法时,这种方式可能存在一定的危险性。


最后修改时间:2016年10月16日16:00:11

参考资料:

《设计模式之禅》

《Java设计模式》


********************************************************************************结束语********************************************************************************************
  我在写这篇博客的时候也是一名初学者,有任何疑问或问题请留言,或发邮件也可以,邮箱为:577328725@qq.com,我会尽早的进行更正及更改。
在我写过的博客中有两篇博客是对资源的整理,可能对大家都有帮助,大家有兴趣的话可以看看!!
下载资料整理——目录:http://blog.csdn.net/fanxiaobin577328725/article/details/51894331
  这篇博客里面是我关于我见到的感觉不错的好资源的整理,里面包含了书籍及源代码以及个人搜索的一些资源,如果有兴趣的可以看看,我会一直对其进行更新和添加。
优秀的文章&优秀的学习网站之收集手册:http://blog.csdn.net/fanxiaobin577328725/article/details/52753638
  这篇博客里面是我对于我读过的,并且感觉有意义的文章的收集整理,纯粹的个人爱好,大家感觉有兴趣的可以阅读一下,我也会时常的对其进行更新。
********************************************************************************感谢********************************************************************************************

0 0