知识大全 Java设计模式之Adapter模式

Posted

篇首语:盛年不重来,一日难再晨,及时当勉励,岁月不待人。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Java设计模式之Adapter模式相关的知识,希望对你有一定的参考价值。

Java设计模式之Adapter模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  通常 客户类(clients of class)通过类的接口访问它提供的服务 有时 现有的类(existing class)可以提供客户类的功能需要 但是它所提供的接口不一定是客户类所期望的 这是由于现有的接口太详细或者缺乏详细或接口的名称与客户类所查找的不同等诸多不同原因导致的

  在这种情况下 现有的接口需要转化(convert)为客户类期望的接口 这样保证了对现有类的重用 如果不进行这样的转化 客户类就不能利用现有类所提供的功能 适配器模式(Adapter Pattern)可以完成这样的转化 适配器模式建议定义一个包装类 包装有不兼容接口的对象 这个包装类指的就是适配器(Adapter) 它包装的对象就是适配者(Adaptee) 适配器提供客户类需要的接口 适配器接口的实现是把客户类的请求转化为对适配者的相应接口的调用 换句话说 当客户类调用适配器的方法时 在适配器类的内部调用适配者类的方法 这个过程对客户类是透明的 客户类并不直接访问适配者类 因此 适配器可以使由于接口不兼容而不能交互的类可以一起工作(work together)

  在上面讨论的接口

  ( )     不是指在JAVA编程语言中接口的概念 虽然类的接口可以通过JAVA借扩来定义

  ( )     不是指由窗体和GUI控件所组成的GUI应用程序的用户接口

  ( )     而是指类所暴露的 被其他类调用的编程接口

  类适配器(Class Adapter)VS对象适配器(Object Adapter)

  适配器总体上可以分为两类 类适配器(Class Adapter)VS对象适配器(Object Adapter)

  类适配器

  类适配器是通过继承类适配者类(Adaptee Class)实现的 另外类适配器实现客户类所需要的接口 当客户对象调用适配器类方法的时候 适配器内部调用它所继承的适配者的方法

  对象适配器

  对象适配器包含一个适配器者的引用(reference) 与类适配器相同 对象适配器也实现了客户类需要的接口 当客户对象调用对象适配器的方法的时候 对象适配器调它所包含的适配器者实例的适当方法

  下表是类适配器(Class Adapter)和对象适配器(Object Adapter)的详细不同

  

  补充

  类适配器(Class Adapter)     对象适配器(Object Adapter)

  基于继承概念     利用对象合成

  只能应用在适配者是接口 不能利用它子类的接口 当类适配器建立时 它就静态地与适配者关联     可以应用在适配者是接口和它的所有子类 因为适配器是作为适配者的子类 所以适配器可能会重载适配者的一些行为

  注意 在JAVA中 子类不能重载父类中声明为final的方法      不能重载适配者的方法

  注意:字面上 不能重栽只是因为没有继承 但是适配器提供包装方法可以按需要改变行为

  客户类对适配者中声明为public的接口是可见的      客户类和适配者是完全不关联的 只有适配器才能感知适配者接口

  在JAVA应用程序中

  适用于期待的接口是JAVA接口的形式 而不是抽象地或具体地类的形式 这是因为JAVA编程语言只允许单继承 因此 类适配器设计成适配者的子类      在JAVA应用程序中

  适用于当客户对象期望的接口是抽象类的形式 同时也可以应用于期望接口是Java接口的形式

  例子

  让我们建立一个验证给定客户地址的应用 这个应用是作为大的客户数据管理应用的一部分

  让我们定义一个Customer类

  Customer

  

  Figure : Customer Class

  Listing : Customer Class

  class Customer

  public static final String US = US ;

  public static final String CANADA = Canada ;

  private String address;

  private String name;

  private String zip state type;

  public boolean isValidAddress()

  …

  …

  

  public Customer(String inp_name String inp_address

  String inp_zip String inp_state

  String inp_type)

  name = inp_name;

  address = inp_address;

  zip = inp_zip;

  state = inp_state;

  type = inp_type;

  

  //end of class

  不同的客户对象创建Customer对象并调用(invoke)isValidAddress方法验证客户地址的有效性 为了验证客户地址的有效性 Customer类期望利用一个地址验证类(address validator class) 这个验证类提供了在接口AddressValidator中声明的接口

  Listing : AddressValidator as an Interface

  public interface AddressValidator

  public boolean isValidAddress(String inp_address

  String inp_zip String inp_state);

  //end of class

  让我们定义一个USAddress的验证类 来验证给定的U S地址

  Listing : USAddress Class

  class USAddress implements AddressValidator

  public boolean isValidAddress(String inp_address

  String inp_zip String inp_state)

  if (inp_address trim() length() < )

  return false;

  if (inp_zip trim() length() < )

  return false;

  if (inp_zip trim() length() > )

  return false;

  if (inp_state trim() length() != )

  return false;

  return true;

  

  //end of class

  USAddress类实现AddressValidator接口 因此Customer对象使用USAddress实例作为验证客户地址过程的一部分是没有任何问题的

  Listing : Customer Class Using the USAddress Class

  class Customer

  …

  …

  public boolean isValidAddress()

  //get an appropriate address validator

  AddressValidator validator = getValidator(type);

  //Polymorphic call to validate the address

  return validator isValidAddress(address zip state);

  

  private AddressValidator getValidator(String custType)

  AddressValidator validator = null;

  if (custType equals(Customer US))

  validator = new USAddress();

  

  return validator;

  

  //end of class

  

  Figure : Customer/USAddress Validator?Class Association

  但是当验证来自加拿大的客户时 就要对应用进行改进 这需要一个验证加拿大客户地址的验证类 让我们假设已经存在一个用来验证加拿大客户地址的使用工具类CAAddress

  从下面的CAAdress类的实现 可以发现CAAdress提供了客户类Customer类所需要的验证服务 但是它所提供的接口不用于客户类Customer所期望的 从下面的CAAdress类的实现 可以发现CAAdress提供了客户类Customer类所需要的验证服务 但是它所提供的接口不用于客户类Customer所期望的

  Listing : CAAdress Class with Inpatible Interface

  class CAAddress

  public boolean isValidCanadianAddr(String inp_address

  String inp_pcode String inp_prvnc)

  if (inp_address trim() length() < )

  return false;

  if (inp_pcode trim() length() != )

  return false;

  if (inp_prvnc trim() length() < )

  return false;

  return true;

  

  //end of class

  CAAdress类提供了一个isValidCanadianAddr方法 但是Customer期望一个声明在AddressValidator接口中的isValidAddress方法

  接口的不兼容使得Customer对象利用现有的CAAdress类是困难的 一种意见是改变CAAdress类的接口 但是可能会有其他的应用正在使用CAAdress类的这种形式 改变CAAdress类接口会影响现在使用CAAdress类的客户

  应用适配器模式 类适配器CAAdressAdapter可以继承CAAdress类实现AddressValidator接口

  

  Figure : Class Adapter for the CAAddress Class

  Listing : CAAddressAdapter as a Class Adapter

  public class CAAddressAdapter extends CAAddress

  implements AddressValidator

  public boolean isValidAddress(String inp_address

  String inp_zip String inp_state)

  return isValidCanadianAddr(inp_address inp_zip

  inp_state);

  

  //end of class

  因为适配器CAAdressAdapter实现了AddressValidator接口 客户端对象访问适配器CAAdressAdapter对象是没有任何问题的 当客户对象调用适配器实例的isValidAddress方法的时候 适配器在内部把调用传递给它继承的isValidCanadianAddr方法

  在Customer类内部 getValidator私有方法需要扩展 以至于它可以在验证加拿大客户的时候返回一个CAAdressAdapter实例 返回的对象是多态的 USAddress和CAAddressAdapter都实现了AddressValidator接口 所以不用改变

  Listing : Customer Class Using the CAAddressAdapter Class

  class Customer

  …

  …

  public boolean isValidAddress()

  //get an appropriate address validator

  AddressValidator validator = getValidator(type);

  //Polymorphic call to validate the address

  return validator isValidAddress(address zip state);

  

  private AddressValidator getValidator(String custType)

  AddressValidator validator = null;

  if (custType equals(Customer US))

  validator = new USAddress();

  

  if (type equals(Customer CANADA))

  validator = new CAAddressAdapter();

  

  return validator;

  

  //end of class

  CAAddressAdapter设计和对AddressValidator(声明期望的接口)对象的多态调用使Customer可以利用接口不兼容CAAddress类提供的服务

  

  Figure : Address Validation Application?Using Class Adapter

  

  Figure : Address Validation Message Flow?Using Class Adapter

  作为对象适配器的地址适配器

  当讨论以类适配器来实现地址适配器时 我们说客户类期望的AddressValidator接口是Java接口形式 现在 让我们假设客户类期望AddressValidator接口是抽象类而不是java接口 因为适配器CAAdapter必须提供抽象类AddressValidatro中声明的接口 适配器必须是AddressValidator抽象类的子类 实现抽象方法

  Listing : AddressValidator as an Abstract Class

  public abstract class AddressValidator

  public abstract boolean isValidAddress(String inp_address

  String inp_zip String inp_state);

  //end of class

  Listing : CAAddressAdapter Class

  class CAAddressAdapter extends AddressValidator

  …

  …

  public CAAddressAdapter(CAAddress address)

  objCAAddress = address;

  

  public boolean isValidAddress(String inp_address

  String inp_zip String inp_state)

  …

  …

  

  //end of class

  因为多继承在JAVA中不支持 现在适配器CAAddressAdapter不能继承现有的CAAddress类 它已经使用了唯一一次继承其他类的机会

  应用对象适配器模式 CAAddressAdapter可以包含一个适配者CAAddress的一个实例 当适配器第一次创建的时候 这个适配者的实例通过客户端传递给适配器 通常 适配者实例可以通过下面两种方式提供给包装它的适配器

  ( )     对象适配器的客户端可以传递一个适配者的实例给适配器 这种方式在选择类的形式上有很大的灵活性 但是客户端感知了适配者或者适配过程 这种方法在适配器不但需要适配者对象行为而且需要特定状态时很适合

  ( )     适配器可以自己创建适配者实例 这种方法相对来说缺乏灵活性 适用于适配器只需要适配者对象的行为而不需要适配者对象的特定状态的情况

  

  Figure : Object Adapter for the CAAddress Class

  Listing : CAAddressAdapter as an Object Adapter

  class CAAddressAdapter extends AddressValidator

  private CAAddress objCAAddress;

  public CAAddressAdapter(CAAddress address)

  objCAAddress = address;

  

  public boolean isValidAddress(String inp_address

  String inp_zip String inp_state)

  return objCAAddress isValidCanadianAddr(inp_address

  inp_zip inp_state);

  

  //end of class

  当客户对象调用CAAddressAdapter(adapter)上的isValidAddress方法时 适配器在内部调用CAAddress(adaptee)上的isValidCanadianAddr方法

  

  Figure : Address Validation Application?Using Object Adapter

  从这个例子可以看出 适配器可以使Customer(client)类访问借口不兼容的CAAddress(adaptee)所提供的服务!

cha138/Article/program/Java/gj/201311/27273

相关参考

知识大全 25种java模式代码参考手册

  抽象工厂(AbstractFactory)模式意图:为特定的客户(或情况)提供特定系列的对象  类的适配器(Adapter)模式意图:将一个类的接口转换成客户希望的另外一个接口  对象的适配器(A

知识大全 C#中的Adapter设计模式浅析

C#中的Adapter设计模式浅析  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  意图  把一个

知识大全 适配器(adapter)模式

  适配器模式的宗旨是保留现有类提供的服务向客户提供接口使得原本接口不兼容而功能相同的类一起工作客户提供接口让实现一些个功能而我们已经有类实现了相同的功能但是两者的接口是不兼容的现在可以实现一个新的类

知识大全 教程:适配器模式(Adapter Pattern)组图

教程:适配器模式(AdapterPattern)组图  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

知识大全 Java设计模式之Strategy模式

Java设计模式之Strategy模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Strat

知识大全 Java设计模式之Observer模式

Java设计模式之Observer模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Obser

知识大全 Java设计模式之Command 模式

Java设计模式之Command模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Comman

知识大全 Java设计模式之计数代理模式

Java设计模式之计数代理模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  描述    计数代

知识大全 Java设计模式之Decorator模式

Java设计模式之Decorator模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  JDK为

知识大全 Java设计模式之迭代器模式

Java设计模式之迭代器模式  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!一引言  迭代这个名词对