适配器模式

来源:互联网 发布:激光熔覆技术知乎 编辑:程序博客网 时间:2024/06/06 08:34

•在软件系统中,由于应用环境的变化,常常需要将“一些现存的对象”放在新的环境中应用,但是新环境要求的接口是这些现存对象所不满足的。那么如何应对这种“迁移的变化”?如何既能利用现有对象的良好实现,同时又能满足新的应用环境所要求的接口?这就是本文要说的Adapter 模式。

新环境如测试中用的testXXX方法,现存对象就是junit框架中原本有的东西

将一个类的接口(Adaptee)转换成客户希望的另外一个接口(Adapter)。Adapter模式使得原本由于接口不兼容(Target和Adaptee不兼容,不在一起的)而不能一起工作的那些类可以一起工作

适配器角色的组成:

•目标抽象角色(Target)
–定义客户要用的特定领域的接口
•适配器(Adaptee)
–定义一个接口,Adapter需要接入

•适配器(Adapter)
–调用另一个接口,作为一个转换器
•客户端(Client)
–协同对象符合Adapter适配器

适配器模式(Adapter Pattern)主要分为三种:
1) 基于类的继承方式
2) 基于对象组合方式
3) 缺省的适配器模式(AWT,Swing事件模型所采用的模式)

第一种代码:

目标抽象角色:

public interface Target {//这个是客户能使用的
 public void method1();
}

适配器(Adaptee):

public class Adaptee {//这个是客户无法直接使用的,即访问不了.
 public void method2(){
  System.out.println("目标方法");
 }
}

适配器(Adapter):

/**
 * Adapter是用来适配Adaptee的,把Adaptee的method2方法适配到method1上去
 * @author Administrator
 *
 */
public class Adapter extends Adaptee implements Target{
 @Override
 public void method1() {
  this.method2();
 }
}

客户端(Client)
public class Client {
 public static void main(String[] args) {
  Target t=new Adapter();
  t.method1();
 }
}
2) 基于对象组合方式:在适配器中持有对客户无法访问的那个Adaptee的对象的引用

public class Adapter implements Target{

 private Adaptee adaptee;
 public Adapter(Adaptee adaptee){
  this.adaptee=adaptee;
 }
 
 @Override
 public void method1() {
  adaptee.method2();
 }

}

缺省的适配器模式:AWT里面用到的那种就是了.对某一个方法感兴趣才去override它

 

在junit中如何体现的呢?就体现在那个runTest方法上:

在runBare方法中,通过runTest方法将我们自己编写的testXXX方法进行了适配,使得JUnit可以执行我们自己编写的Test Case,runTest方法的实现如下:

/**
  * Override to run the test and assert its state.
  * @exception Throwable if any exception is thrown
  */
 protected void runTest() throws Throwable {
  assertNotNull(fName);
  Method runMethod= null;
  try {
   // use getMethod to get all public inherited
   // methods. getDeclaredMethods returns all
   // methods of this class but excludes the
   // inherited ones.
   runMethod= getClass().getMethod(fName, null);
  } catch (NoSuchMethodException e) {
   fail("Method /""+fName+"/" not found");
  }
  if (!Modifier.isPublic(runMethod.getModifiers())) {
   fail("Method /""+fName+"/" should be public");
  }

  try {
   runMethod.invoke(this, new Class[0]);
  }
  catch (InvocationTargetException e) {
   e.fillInStackTrace();
   throw e.getTargetException();
  }
  catch (IllegalAccessException e) {
   e.fillInStackTrace();
   throw e;
  }
 }

在runTest方法中,首先获得我们自己编写的testXXX方法所对应的Method对象(不带参数),然后检查该Method对象所对应的方法是否是public的,如果是则调用Method对象的invoke方法来去执行我们自己编写的testXXX方法。

其实在这里的客户就是junit的运行器,它原本是无法去访问我们自己所写的testXXX方法的

需要注意的是:junit并不是对这个模式照本宣科的用上去

与代理模式的意图的区别就是代理模式它不需要去增加一些功能,仅仅是需要用那个方法.