`
yahaitt
  • 浏览: 756540 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

java Adapter模式

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

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

  在上面讨论的接口:

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

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

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

  类适配器(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类:
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中声明的接口。
 
public interface AddressValidator {
  public boolean isValidAddress(String inp_address,
     String inp_zip, String inp_state);
}//end of class


让我们定义一个USAddress的验证类,来验证给定的U.S地址。
class USAddress implements AddressValidator {
  public boolean isValidAddress(String inp_address,
     String inp_zip, String inp_state) {
   if (inp_address.trim().length() < 10)
     return false;
   if (inp_zip.trim().length() < 5)
     return false;
   if (inp_zip.trim().length() > 10)
     return false;
   if (inp_state.trim().length() != 2)
     return false;
   return true;
   }
}//end of class


USAddress类实现AddressValidator接口,因此Customer对象使用USAddress实例作为验证客户地址过程的一部分是没有任何问题的。
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




但是当验证来自加拿大的客户时,就要对应用进行改进。这需要一个验证加拿大客户地址的验证类。让我们假设已经存在一个用来验证加拿大客户地址的使用工具类CAAddress。
        从下面的CAAdress类的实现,可以发现CAAdress提供了客户类Customer类所需要的验证服务。但是它所提供的接口不用于客户类Customer所期望的。从下面的CAAdress类的实现,可以发现CAAdress提供了客户类Customer类所需要的验证服务。但是它所提供的接口不用于客户类Customer所期望的。
class CAAddress {
  public boolean isValidCanadianAddr(String inp_address,
     String inp_pcode, String inp_prvnc) {
   if (inp_address.trim().length() < 15)
     return false;
   if (inp_pcode.trim().length() != 6)
     return false;
   if (inp_prvnc.trim().length() < 6)
     return false;
   return true;
   }
}//end of class


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

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

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


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接口,所以不用改变。

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类提供的服务。




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

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

public abstract class AddressValidator {
  public abstract boolean isValidAddress(String inp_address,
     String inp_zip, String inp_state);
}//end of class
Listing 20.9: 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的一个实例。当适配器第一次创建的时候,这个适配者的实例通过客户端传递给适配器。通常,适配者实例可以通过下面两种方式提供给包装它的适配器。

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

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



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方法。



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











分享到:
评论
2 楼 dimaomao 2011-07-05  
哦 ,另外UML图画的听不错的
1 楼 dimaomao 2011-07-05  
写的较全面,不过后半部分,看起来优点晕,确实语言描述起来困难。

相关推荐

    Java-从Decorator,Adapter模式看Java/IO

    Java-从Decorator,Adapter模式看Java/IO 讲得很详细

    java 汽车适配器(Adapter适配器模式)

    java 汽车适配器(Adapter适配器模式) java 汽车适配器(Adapter适配器模式)

    Java优良的Adapter模式:适配器模式

    自己总结了一个在性能和结构上都很容易理解的Adapter模式。  Adapter模式也叫适配器模式,是由GoF提出的23种设计模式的一种。Adapter模式是构造型模式之一,通过Adapter模式,可以改变已有类(或外部类)的接口...

    [Java设计模式(第2版)(Design.Patterns.in.Java).John.Metsker

    第3章 适配器(adapter)模式 13 第4章 外观(facade)模式 27 第5章 合成(composite)模式 39 第6章 桥接(bridge)模式 52 第7章 职责型模式介绍 62 第8章 单例(singleton)模式 67 第9章 观察者(observer)模式 72 第10章 ...

    JAVA设计模式之结构模式

    这是JAVA设计模式中属于结构模式的部分,包括Flyweight(共享模式)、Bridge(桥模式)、Decorator(装饰模式)、Composite(组合模式)、Adapter(适配器模式)、Proxy(代理模式)、Facade (外观模式)的源代码。其中有些模式中...

    【动力节点】Java视频教程_Adapter设计模式

    教程名称: 【动力节点】Java视频教程_Adapter设计模式本套Java视频教程详细讲解了适配器设计模式的用法。首先在Java视频中介绍了适配器模式的基本元素及其定义,然后先使用无适配器模式编程,再使用多功能适配器及...

    java设计模式之适配器模式

    java设计模式之适配器模式,希望对大家有所帮助。

    java设计模式之适配器模式(Adapter)

    主要介绍了java设计模式之适配器模式Adapter的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    33种JAVA设计模式DEMO

    适配器模式(Adapter Pattern) 桥接模式(Bridge Pattern) 过滤器模式(Filter、Criteria Pattern) 组合模式(Composite Pattern) 装饰器模式(Decorator Pattern) 外观模式(Facade Pattern) 享元模式...

    JAVA设计模式chm文档

    设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制) 设计模式之Observer ...

    java设计模式教程+源代码

    Adapter ( 适配器模式 ) Bridge ( 桥接模式 ) Composite ( 组合模式 ) Decorator ( 装饰模式 ) Facade ( 外观模式 ) Flyweight ( 享元模式 ) Proxy ( 代理模式 ) Chain of Responsibility ( 责任链模式 ) ...

    23种设计模式的实现(Java 版),java设计模式

    Factory模式,Prototype模式,Builder 模式,Singleton模式,Facade模式,Proxy模式,Adapter模式,Composite模式,Decorator模式....

    JAVA 设计模式PPT

    首先介绍了Java中面向对象特性和技术,逐个分析Abstract Factory;Builder;Prototype;Singleton;Adapter (对象);Bridge;Composite;Decorator;Facade;Flyweight;Proxy;Iterator;Observer等模式

    Java设计模式之适配器模式(Adapter模式)介绍

    主要介绍了Java设计模式之适配器模式(Adapter模式)介绍,本文讲解了为何使用适配器模式、如何使用适配器模式等内容,需要的朋友可以参考下

    Java设计模式

    Adapter: 把一个接口或是类变成另外一种。 ● java.util.Arrays#asList() ● javax.swing.JTable(TableModel) ● java.io.InputStreamReader(InputStream) ● java.io.OutputStreamWriter(OutputStream) ● ...

    java设计模式期末考试选择题100道

    适合Java设计模式期末考试选择题复习,形式如下: 10.(单选题)Facade(外观)模式的意图是 正确答案: A A.希望简化现有系统的使用方法,你需要定义自己的接口 B.将一个无法控制的现有对象与一个特定借口相匹配。 C....

    用Java实现23种设计模式

    用Java实现23种设计模式 1. 创建型模式 工厂模式(Factory Pattern) 抽象工厂模式(Abstract Factory Pattern) 单例模式(Singleton Pattern) 建造者模式(Builder Pattern) 原型模式(Prototype Pattern)...

    Java设计模式之Adapter适配器模式

    主要为大家详细介绍了Java设计模式之Adapter适配器模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

    23种设计模式的java源代码

    里面包含了23中设计模式源代码,其中包括工厂模式(Factory)、单例(Singleton)、观察者模式(Observer)、适配器模式(Adapter)、Template模式、Decorate模式、proxy模式等 这些代码对于初学者看起来稍微复杂一些,我...

    Java面试 java设计模式整理 单例、工厂、策略等 面试使用,学习使用

    java的设计模式大体上分为三大类: 2 设计模式遵循的原则有6个: 2 1. 工厂模式(Factory Method) 2 2. 抽象工厂模式(Abstract Factory) 3 3. 单例模式(Singleton) 4 4.建造者模式(Builder) 4 5. 原型模式...

Global site tag (gtag.js) - Google Analytics