設計模式之適配器模式

序言

在以前學習適配器模式時,有個經典例子:就是有些電器的工作電壓不是220V, 比如電腦工作電壓20V,但是我們家庭用電的電壓是220。怎麼讓20V的電腦在220V的電壓下工作,這就需要一個電源適配器——俗稱充電器或變壓器。有了這個電源適配器 家庭的用電電壓跟電腦的用電電壓 即可兼容。

適配器模式

定義: 將一個接口轉換成客戶所希望的另一個接口,使接口不兼容的那些類可以一起工作,其別名爲爲包裝器(Wrapper)。適配器模式既可以作爲類結構性模式,也可以作爲對象型結構性模式。

適配器模式結構圖

  • Target(目標抽象類): 目標抽象類定義客戶所需的接口,可以是一個抽象類或接口,也可以是一個具體的類。
  • Adapter(適配器類): 適配器可以調用另外一個接口,作爲一個轉換器,對Adaptee和Target進行適配,適配器類是適配器模式的核心。
  • Adaptee(適配者類) : 適配者即被適配的角色,它定義了已存在的接口,這個接口需要適配。一般是一個具體的類,包含了客戶希望使用的業務方法,在某些情況下可能沒有適配者類的源代碼。

在適配器模式結構圖我們可以看到 Adapter(適配器)和Adaptee(適配者)是有一種關聯的,這種關聯可以是繼承關係,也可以是一種組合關係。 繼承關係的我們一般稱爲類適配器模式 ; 組合關係的稱爲對象適配器模式

類適配器模式

定義一個需要被適配的類

/**
* @program
* @Desc  Adaptee(適配者)
* @Author 遊戲人日常
* @CreateTime 2019/07/08--14:49
*/
public class Adaptee {
	public void specificRequest(){
    	System.out.println("將需要被適配的方法");
	}
}

定義一個目標接口

/**
* @program
* @Desc   目標接口
* @Author 遊戲人日常
* @CreateTime 2019/07/08--14:53
*/
public interface Target {
	public void request();
}

定義適配器類, 因爲是類適配器模式,所以我們需要繼承Adaptee類。

/**
* @program
* @Desc    Adapter(適配者)
* @Author 遊戲人日常
* @CreateTime 2019/07/08--14:57
*/
public class Adapter extends Adaptee implements  Target {

	@Override
	public void request() {
    	specificRequest();
	}
	@Override
	public void specificRequest() {
    	//這裏可以加下其他操作
    	super.specificRequest();
    	//這裏可以加下其他操作
	}
}

客戶端測試

   public static void main(String args []){
    Target adapter=new Adapter();
    adapter.request();
   }

輸出結果 :

將需要被適配的方法

這裏我們可以看到適配器(Adapter)繼承了適配者(Adaptee),然後實現了目標接口(Target)。 這樣使目標接口跟適配者的接口就關聯起來了, 客戶端通過調用適配器的方法,從而達到調用了適配者所被適配的方法。

對象適配器模式

對象適配器模式跟類適配器模式所不同的就是適配器(Adapter)類是基於繼承的,而對象適配器是基於組合的。 其他的Target、Adaptee不變。

定義適配器類

/**
* @program
* @Desc    Adapter(適配者)
* @Author 遊戲人日常
* @CreateTime 2019/07/08--14:57
*/
public class Adapter  implements  Target {

	private Adaptee adaptee =new Adaptee();

	@Override
	public void request() {
    	adaptee.specificRequest();
	}
}

客戶端測試

   public static void main(String args []){
    Target adapter=new Adapter();
    adapter.request();
   }

輸出結果 :

將需要被適配的方法

一般常用的就是對象適配器模式,很少用類適配器。 還有一種雙向適配器模式,就是(Adapter)適配器包含對目標類(Target)和適配者類(Adaptee)兩個引用。目標類可以通過適配器(Adapter)調用適配者(Adaptee中的方法, 適配者類也可以通過適配器調用目標類的方法。 UML類圖如下:

雙向適配器模式結構圖

適配器(Adapter)類一般寫法如下:

/**
* @program
* @Desc    Adapter(適配者)
* @Author 遊戲人日常
* @CreateTime 2019/07/08--14:57
*/
public class Adapter  implements  Target , Adaptee {
	
	//同時對適配者和目標類的引用
	private Target  target;
	private Adaptee adaptee;

	public Adapter(Target target) {
    	this.target = target;
	}

	public Adapter(Adaptee adaptee) {
    	this.adaptee = adaptee;
	}

	@Override
	public void request() {
    	adaptee.specificRequest();
	}
	@Override
	public void specificRequest() {
    	target.request();
	}
}

在實際的開發中很少使用雙向適配器。

缺省適配器

缺省適配器模式是適配器模式一種變體。

定義: 當不需要實現一個接口所提供的所有方法時,可以設計一個抽象類實現該接口,併爲每個接口提供一個默認實現,那麼該抽象類的子類可以選擇性覆蓋父類中的方法,它適用於不想使用一個接口中的所有方法的情況,又稱爲單接口適配器模式。

簡單的理解就是當適配者(Adaptee)有大量的方法時,那麼每個適配器(Adapter)都要去實現接口中的這些方法,這樣就感覺太費勁。 所以這種情況下,可以考慮實現個默認的適配器,然後根據實際目標角色接口的類集成這個默認適配器,然後選擇性的實現默認適配器中的一些方法。

缺省適配器模式結構如下圖:

缺省配器模式結構圖

  • ServiceInterface(適配者接口) : 是一個接口,裏面包含大量的方法。
  • AbstractServiceClass(缺省適配器類) : 實現了ServiceInterface中聲明的方法, 通常定義爲抽象類。
  • ConcreteServiceClass(具體業務類) : 它是缺省適配器的子類,在沒有引用適配器之前,它需要實現適配者(ServiceInterface)所有的方法, 有了缺省適配器類後,就可以有選擇性的覆蓋適配器類中的方法。

總結

適配器模式總共列出四種: 類適配器模式、 對象適配器模式 、 雙向適配器模式 、 缺省適配器模式。

  • 類適配器模式 : 適配器(Adapter)跟適配者(Adaptee)是一種繼承關係。
  • 對象適配器模式: 適配器(Adapter)跟適配者(Adaptee)是一種組合關係。
  • 雙向適配器模式 : 雙向適配器是對象適配器模式的一種變體, 該模式的適配器(Adapter)不僅引用了適配者(Adaptee),還對目標類(Target)引用。 所以這種模式目標類和適配者之間互相適配。
  • 缺省適配器模式: 當適配者接口中出現大量的方法時,就可以考慮這種模式。

適配器優缺點:

優點 :

類適配器模式和對象適配器模式都具有的優點:

  • 將目標類(Target)和 適配者類(Adaptee)解耦, 引用一個適配器類(Adapter)就可以對適配者進行重用。
  • 增加了類的透明性和複用性,將具體的業務實現過程封裝在適配者類中,對客戶端來而言是透明的,而且提高了適配者的複用性,同一個適配者類可以在多個不同的系統中複用。

對象適配器模式優點:

  • 一個對象適配器可以把多個適配者適配到同一目標。
  • 可以適配一個適配者的子類,由於適配器和適配者之間是組合關係,根據”里氏代換原則“
    ,適配者的子類也可以通過該適配器進行適配。

缺點:

類適配器模式缺點:

  • 因爲Java不支持多重繼承,一次最多適配一個適配者類,不能同時適配多個適配者。
  • 適配者類不能爲最終類,即適配者類不能用final關鍵字修飾。
  • 類適配器模式中的目標類只能爲接口,不能爲類。

對象適配器模式缺點:

  • 與類適配器模式相比,要在適配器中置換適配者類的某些方法比較麻煩(因爲類適配器模式是基於繼承的,可以重寫適配者類的方法,對象適配器模式則不能),如果一定要置換掉適配者類的方法,可以先做一個適配者的子類,將適配者類的方法置換掉,然後再把適配者的子類當作真正的適配者進行適配,實現過程較爲複雜。

適用場景

  • 系統需要使用一些現有的類,而這些類的接口(如方法名)不符合需要。
  • 想創建一個可以重用的類,用於與一些彼此之間沒有太大的關聯的一些類,包括一些可能再將來引進的類一起工作。

參考

https://blog.csdn.net/LoveLion/article/details/17517213

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