适配器模式

2   Adapter模式

    适配器模式俗称变压器模式,指将一个类的接口变换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。从功能上讲这些接口不兼容的类一般具有相同或相似的功能。通常我们通过修改该类的接口来解决这种接口不兼容的情形,但是如果我们不愿意为了一个应用而修改各原有的接口,或者我们压根就没有原有对象的源代码那该怎么办呢? 此时Adapter模式就会派上大用场了。

 

2.1 适配器模式的几个要素

    适配器模式所涉及的角色包括:1.源;2.目标;3.适配器;4.客户。

1.      源(Adaptee):已经存在的、需要适配的类。

2.      目标(Target):客户所期待的接口。目标可以是具体的或抽象的类,也可以是接口。

3.      适配器(Adapter):适配器模式的核心类。有两种方式实现Adapter,对象适配器(Object Adapter)和类适配器(Class Adapter)。

4.      客户(Client):

    下图是Adapter设计模式中的几个对象:

   图3  适配器的类图 

2.2 Adapter模式的使用场景和意图

     “The Adapter Pattern converts the interface of a class into another interface the clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.”

                         --GOF 《Element of reusable Object-Oriented Software》

       上面是GOF在《可复用元素面向对象》这本书中对适配器模式的概括。很经典的一句话。

    从上图我们可以看出Adapter模式使用的场景:我们的新系统中有一个客户(Client)需要一个Target的接口,原有的系统中有一个现成的类(Adaptee),该类具有Target接口所需的功能。但是Adaptee类提供的接口却与客户需要的Target接口不同。在这种情况下,我们希望将现有的接口(Adaptee)转化(convert)为客户类期望的接口(Target),这样不仅保证没有修改原有的系统,更主要的是还能保证对现有类的重用。若不进行这样的转化,客户类就不能利用现有类所提供的功能。

    因此在客户需要的接口Target和原系统中具有此功能的类Adaptee间必然需要一个“调停者”对象,根据该对象的功能可以确定此“调停者”必须具有以下两个特点:1.实现Target接口;2.重用Adaptee。该“调停者”就是适配器模式的主角――Adapter类。首先他实现了客户需要的Target接口,因此他可以满足客户(Client)的需要,同时它又重用的原有系统的Adaptee类。

    在前面我们讲过在Java中有两种方式可以达到重用的目的:1.继承;2.包含。同样在适配器模式中也可以通过这两种方式达到重用Adaptee类的目的。根据重用使用方式的不同一般将适配器模式分为两类:类适配器(Class Adapter)和对象适配器(Object Adapter)。

 

2.3 类适配器 VS 对象适配器

       要正确地区别这两种适配器的区别,我们还是从一个简单的例子开始吧!我们的系统中有一个具有某个特定功能的类Adaptee,一个客户类Client――他需要一个实现Target接口的对象,和一个Target接口,以下是他们的源码:

 

//Adaptee.java

public class Adaptee{

         public void specialRequest(){

                   System.out.println("Called SpecificRequest() in Adaptee ");

         }       

}

 

//Client.java

public class Client {

         public static void main(String[] args){

                   Target t =   ……     //new Adapter() ;

                   t.request();

         }

}

 

 

//Target.java

public interface Target{

         public void request();

}

 

       根据上一小节的分析我们知道此时需要一个Adapter对象,该对象实现Target接口,同时他又重用现有的Adaptee类。任何有一点点OO(面向对象)知识的人都会想到通过继承可以达到重用的目的。下面是通过继承实现Adaptee类重用的例子:

//Adapter.java

public class Adapter extends Adaptee implements Target{

         public void request(){

                   this.specialRequest();

         }

}

       简单明了!现在的过程就是:客户调用Target接口的request方法,实际就是调用其父类AdapteespecialRequest方法。图4为类适配器(Class Adapter)的类图:

 

图4  类适配器(Class Adapter)的类图

    这就是大家通常常说的类的适配器!类适配器具有以下的两个特点:1.适配器类(Adapter)实现Target接口;2. 适配器类(Adapter)通过继承来实现对Adaptee类的重用。

    下面是一个通过组合关系实现继承的例子,以下是源码:

//Adapter.java

public class Adapter implements Target{

         Adaptee adaptee = new Adaptee();

         public void request(){

                   adaptee.specialRequest();

         }

}

    以上就是通过组合实现对Adaptee类重用的例子。这就是大家通常说的对象的适配器!对象的适配器具有以下的两个特点:1.适配器类(Adapter)实现Target接口;2. 适配器类(Adapter)通过组合来实现对Adaptee类的重用。图5是对象适配器的类图。

图5 对象适配器类图

    对于这两者不同的适配器客户代码其实是完全一样的。以下是客户的代码:

//Client.java

public class Client {

         public static void main(String[] args){

                   Target t = new Adapter() ;

                   t.request();

         }

}

2.4 适配器模式的变体

       上面谈到的所有适配器都是通过重用Adaptee类从而实现Target接口中的方法。这只是具体层次的重用。是否还存在更高层次的适配器呢!?答案是肯定的!我们不仅可以适配具体的类还可以适配抽象类,甚至适配接口!下面是这种适配的简图:

 

6 接口的适配

 

       从上图可以看出:AdapterAdaptee接口适配为客户Client需要的接口Target,这样在整个系统中所有实现Adaptee接口的类都可以通过Adapter适配为Target对象,从而避免为每一个类都写一个适配器。后面会给大家带来一个JDK中使用此中适配的例子。我们不仅仅可以象上面一样对接口进行适配,也可以对抽象类进行适配!主要是根据系统的需求,确定此时的场景是否适合使用适配器模式!

 

       以上是适配器模式!关于 IO的适配在下面的源代码分析中,会阐述 byte数组到 InputStream的适配。就当作一个适配器的例子吧!其它关于适配器在 Java中的应用以及如何将 java.sql.ResultSet适配至 javax.swing.table.TableModel、将 FileDOM树、 Thread适配至 javax.swing.tree.TreeModel就不在这里详细讲解了
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值