學習:java設計模式—Adapter模式

1、核心意圖:
    將一個類的接口轉換成客戶希望的另外一個接口,從而使得原本由於接口不兼容而不能一起工作的類可以一起工作。
該模式的目標是通過一個代理(這裏是Adapter),在原來的類(Adaptee)和客戶(Client)之間進行協調,從而達到兼容的目的。其核心是解決一致性的問題。
2、身邊實例:
在我們實際生活中也很容易看到這方面的例子,比如我們要和一個外國人打交道,例如韓國 人,如果我們沒有學習過韓語,這個韓國人也沒有學習過我們漢語,在這種情況下,我們之間是很難進行直接交流溝通。爲了達到溝通的目的有兩個方法:1)改造 這個韓國人,使其能夠用漢語進行溝通;2)請一個翻譯,在我們和這個韓國人之間進行語言的協調。顯然第一種方式——改造這個韓國人的代價要高一些,我們不 僅要重新培訓他漢語的學習,還有時間、態度等等因素。而第二個方式——請一個翻譯,就很好實現,而且成本低,還比較靈活,當我們想換個日本人,再換個翻譯 就可以了。
3、動機簡述:
在該模式的動機中,描述了一個繪圖編輯器的實現,該編輯器可以對基本圖元Shape(直 線、多邊形、正文等)進行繪製和排列來生成圖片和圖表,對於這些圖元類的實現,直線/多邊形還比較容易實現,但是正文的實現卻很麻煩,爲了減少開發成本和 保證質量,通過採用Adapter模式定義適配器類TextShape,來重用圖形工具箱中已經存在的正文編輯器TextView。
4、Java實現分析:
在GOF設計模式中,Adapter可以分爲類模式和對象模式兩種,類模式通過多重繼承實現,對象模式通過委託實現。
在Java中由於沒有多重繼承機制,所以要想實現類模式的Adapter,就要進行相應 的改變:通過繼承Adaptee類實現Target接口方式實現。這種改變存在兩個問題:1)Target必須是一個接口而不能是一個類,否則Adapter無法implements實現;2)Adapter是繼承Adaptee的實現,而不是私有繼承,這就表示Adapter是一個Adaptee的子類。
類Adapter模式和對象Adapter模式的Java代碼可參考本文下方代碼部分。
5、類模式/對象模式分析:
由於存在兩種Adapter實現方式(即使在Java中),那麼在實際中我們採用哪一種要好呢?通過分析發現這兩種模式有兩個主要特性區別,並且還是互補的:
A、表現在Adapter對Adaptee的特殊性要求:
類模式由於Adapter是Adaptee的子類,所以Adapter很方便重新定義Adaptee中的個別方法,以達到自己的特性需要。
對象模式由於Adapter不是Adaptee的子類,所以如果Adapter對Adaptee中的個別方法有特殊的需要,就要新建Adaptee的子類,而讓Adapter使用這個子類。
B、表現在Adaptee的類層次擴展上:
類模式由於Adapter是Adaptee的子類,所以編譯後就不能再更換所實現的父類Adaptee,因此如果有一個Adaptee的類層次結構,就要相應的有一個Adapter的類層次結構,且新擴展Adaptee時很不方便。
對象模式由於Adapter不是Adaptee的子類,而是通過使用的方式,所以在系統運行時仍然可以更換Adapter所使用的Adaptee,只要他們具有相同的類型。所以在新擴展Adaptee時很方便。
6、Java代碼示例—對象模式實現:
類Point,表示畫面座標中的點
package qinysong.pattern.adapter;

public class Point {
 
private int coordinateX;
 
private int coordinateY;

 
public Point(int coordinateX, int coordinateY){
   
this.coordinateX = coordinateX;
   
this.coordinateY = coordinateY;
  }

 
public String toString(){
   
return "Point[x=" + coordinateX + ",y=" + coordinateY + "]";
  }

 
public int getCoordinateX() {
   
return coordinateX;
  }

 
public int getCoordinateY() {
   
return coordinateY;
  }

}

類Shape,表示圖元藉口,對應Adapter模式中的Target
package qinysong.pattern.adapter;

public interface Shape {
 
public Point getBottomLeftPoint();
 
public Point getTopRightPoint();
}

類TextView,工具箱中的文本組件類,已經存在的類,對應Adapter模式中的Adaptee
package qinysong.pattern.adapter;

public class TextView {

 
public int getCoordinateX() {
    System.out.println(
"TextView.getCoordinateX()...");
   
return 10;
  }

 
public int getCoordinateY() {
    System.out.println(
"TextView.getCoordinateY()...");
   
return 20;
  }

 
public int getHeight() {
    System.out.println(
"TextView.getHeight()...");
   
return 30;
  }

 
public int getWidth() {
    System.out.println(
"TextView.getWidth()...");
   
return 40;
  }

 
public boolean isEmpty(){
   
return false;
  }

}

類TextShape,對象模式實現的Adapter
package qinysong.pattern.adapter;

public class TextShape implements Shape {
 
private TextView textView;

 
public TextShape(TextView textView){
   
this.textView = textView;
  }


 
//通過TextView的實例進行協調實現
  public Point getBottomLeftPoint() {
    System.out.println(
"TextShape.getBottomLeftPoint()...");
   
int coordinateX = textView.getCoordinateX();
   
int coordinateY = textView.getCoordinateY();
   
return new Point(coordinateX, coordinateY);
  }


 
//通過TextView的實例進行協調實現
  public Point getTopRightPoint() {
    System.out.println(
"TextShape.getTopRightPoint()...");
   
int coordinateX = textView.getCoordinateX();
   
int coordinateY = textView.getCoordinateY();
   
int height = textView.getHeight();
   
int width = textView.getWidth();
   
return new Point(coordinateX + width, coordinateY + height);
  }

}

類Client,Adapter模式的客戶
package qinysong.pattern.adapter;

public class Client {
 
public static void main(String[] args){
    System.out.println(
"Client.main begin ..........");
    System.out.println(
"Client.main 以下是通過實例委託方式實現的Adapter");
    Shape shape
= new TextShape(new TextView());
    Point bottomLeft
= shape.getBottomLeftPoint();
    Point topRight
= shape.getTopRightPoint();
    System.out.println(
"Client.main shape's bottomLeft:" + bottomLeft);
    System.out.println(
"Client.main shape's topRight:" + topRight);

    System.out.println(
" Client.main 以下是通過類繼承方式實現的Adapter");
    Shape shape2
= new TextShape2();
    bottomLeft
= shape2.getBottomLeftPoint();
    topRight
= shape2.getTopRightPoint();
    System.out.println(
"Client.main shape2's bottomLeft:" + bottomLeft);
    System.out.println(
"Client.main shape2's topRight:" + topRight);
    System.out.println(
"Client.main end   ..........");
  }

}

7、Java代碼示例—類模式實現:
和以上對象模式實現中的示例目的相同,類Point、Shape、TextView相同,略。以下是類TextShape2的示例代碼,實現類模式的Adapter
package qinysong.pattern.adapter;

public class TextShape2 extends TextView implements Shape {

 
//通過所繼承的TextView,進行協調實現
  public Point getBottomLeftPoint() {
    System.out.println(
"TextShape2.getBottomLeftPoint()...");
   
int coordinateX = getCoordinateX();
   
int coordinateY = getCoordinateY();
   
return new Point(coordinateX, coordinateY);
  }


 
//通過所繼承的TextView,進行協調實現
  public Point getTopRightPoint() {
    System.out.println(
"TextShape2.getTopRightPoint()...");
   
int coordinateX = getCoordinateX();
   
int coordinateY = getCoordinateY();
   
int height = getHeight();
   
int width = getWidth();
   
return new Point(coordinateX + width, coordinateY + height);
  }


 
//注意: 這一點體現了類模式的優勢,可以很方便地重定義父類TextView中的方法
  public int getCoordinateX() {
    System.out.println(
"TextShape2.getCoordinateX()...");
   
return 100;
  }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章