熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java高級技術 >> 正文

教程:適配器模式(Adapter Pattern)組圖

2013-11-23 19:53:58  來源: Java高級技術 

  通常客戶類(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的驗證類來驗證給定的US地址
  Listing : USAddress Class
  
  class USAddress implements AddressValidator {
  public boolean isValidAddress(String inp_address
  String inp_zip String inp_state) {
  if (inp_addresstrim()length() < )
  return false;
  if (inp_ziptrim()length() < )
  return false;
  if (inp_ziptrim()length() > )
  return false;
  if (inp_statetrim()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 validatorisValidAddress(address zip state);
  }
  private AddressValidator getValidator(String custType) {
  AddressValidator validator = null;
  if (custTypeequals(CustomerUS)) {
  validator = new USAddress();
  }
  return validator;
  }
  }//end of class
  
 educitycn/img_///jpg >

  Figure : Customer/USAddress Validator?Class Association
  
  但是當驗證來自加拿大的客戶時就要對應用進行改進這需要一個驗證加拿大客戶地址的驗證類讓我們假設已經存在一個用來驗證加拿大客戶地址的使用工具類CAAddress
  
  從下面的CAAdress類的實現可以發現CAAdress提供了客戶類Customer類所需要的驗證服務但是它所提供的接口不用於客戶類Customer所期望的
  Listing : CAAdress Class with Incompatible Interface
  
  class CAAddress {
  public boolean isValidCanadianAddr(String inp_address
  String inp_pcode String inp_prvnc) {
  if (inp_addresstrim()length() < )
  return false;
  if (inp_pcodetrim()length() != )
  return false;
  if (inp_prvnctrim()length() < )
  return false;
  return true;
  }
  }//end of class
  
  CAAdress類提供了一個isValidCanadianAddr方法但是Customer期望一個聲明在AddressValidator接口中的isValidAddress方法
  
  接口的不兼容使得Customer對象利用現有的CAAdress類是困難的一種意見是改變CAAdress類的接口但是可能會有其他的應用正在使用CAAdress類的這種形式改變CAAdress類接口會影響現在使用CAAdress類的客戶
  
  應用適配器模式類適配器CAAdressAdapter可以繼承CAAdress類實現AddressValidator接口
  
 educitycn/img_///jpg>

  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 CAAddre
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27645.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.