java读书笔记-《java设计模式》-第3章 - 适配器模式

来源:互联网 发布:淘宝店基本常识 编辑:程序博客网 时间:2024/06/05 16:33

适配器模式分为 类适配器 和 对象适配器 两种。


两者的区别在于前者是客户端设计的使用接口 与 现有的已实现该功能的功能类组合使用,由于此操作是在类层次上实现的,所以叫类适配器;

而后者客户端并没有设计使用接口,所以通过继承客户端的使用类,并在其中实现已有功能类的实例 来调用已有的功能代码,也就是对象适配器。


首先书中说明了适配器模式的使用情景:通常,在代码已经存在的情况下编写客户端代码,开发人员可以采取模拟客户端的方式调用我们提供的接口对象。然而,客户端代码也可能与你的代码单独进行开发。例如,设计的火箭仿真程序会使用你所提供的火箭信息,但是对于火箭应该拥有怎样的行为,仿真器也会拥有自己的定义。在这样的情况下,会发现现有的类虽然提供了客户端需要的服务,却被定义为不同的方法名。这是,我们就需要使用适配器模式。


接口适配(类适配器)

当我们需要适配现有的代码时,可能会发现客户端开发人员已经事先考虑到这种情况。开发人员为客户端使用的服务提供了接口,例如提供了接口A,A中真正提供服务的是a方法; 但现有代码中提供功能代码的是B类中的b方法。解决方式实现一个类C,C继承自B类并实现了A接口,在C中实现a方法并在a方法中调用父类B的b方法来提供真正的功能代码。

interface A {

  void a();

}

class B {

  void b(){

    此处是真正的功能代码;

  };

}

class C extends B interface A {

  void a() {

     b();

  }

}


对象适配器

但你需要适配的一组方法并非被定义在接口中时,就可以创建一个对象适配器,他使用了委派而非继承。

如果客户端通过类A中的a方法来提供服务,而已经实现功能的代码是在类B的b方法里。那通过实现一个累C(C继承自A),并往C中传入一个或实现一个B的实例, 这样就可以轻松的通过C中的a方法来调用持有真正功能代码的B实例的b方法了。

class A {

  void a(){};

}

class B {

  void b(){

    这里是真正的功能代码;

  }

}

class C extends A {

  B bb;

  public A (B bb) {

     this.bb = bb;

  }

  void b() {

     bb.b();

     //或者不通过传入B的实例,而是直接在C里直接创建一个B实例

     //new B().b();

  }

}

总而言之,对象适配器在一定程度上解决了一个问题,即将对象适配为没有明确定义的接口。


最后,书中提出了一个问题,看似能让人知道应该在何时何地使用哪种方式:

为什么说对象适配器设计要比类适配器设计更有风险?

书中是这样回答的:

1、没有接口规范,可能在运行时出现编译时无法检测到的问题。(具体含义还在探究)

2、对象适配器中,实现的子类可能会访问父类中的变量,但我们不能保证父类中的变量不会被修改,这样就可能会导致错误的出现。而接口就没有这样的问题。