1. 程式人生 > >介面卡模式(Adapter)

介面卡模式(Adapter)

1.簡述

介面卡模式就是將一個類的介面變成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠在一起工作。下面這個例子很好的說明了介面卡的作用

2.角色

  •  目標角色(Target):客戶所期待的介面。目標可以是具體的或抽象的類,也可以是介面。
  • 源角色(Adaptee)也就是被適配的類:需要適配的類或適配者類。
  • 介面卡角色(Adapter):通過包裝一個需要適配的物件,把原介面轉換成目標介面。

3.兩種實現方式和UML類圖

(1).類的介面卡模式(採用繼承實現)

 

(2).物件介面卡(採用物件組合方式實現)

4.通用程式碼

(1).類介面卡通用程式碼:

/*
 *	目標角色
 */
interface Target {
	// 目標角色有自己的方法
	public void request();
}

/*
 * 目標角色的實現類
 */
class ConcreteTarget implements Target {

	public void request() {
		System.out.println("我是目標角色的業務邏輯");
	}
}

/*
 * 源角色
 */
class Adaptee {
	// 原有的業務邏輯
	public void doSomething() {
		System.out.println("我是被適配角色的業務邏輯");
	}
}

/*
 * 介面卡角色
 */
class Adapter extends Adaptee implements Target {
	public void request() {
		super.doSomething();
	}
}

public class Client {
	public static void main(String[] args) {
		// 如果要使用原有的業務邏輯
		Target target = new ConcreteTarget();
		target.request();
		// 現在增加了介面卡角色後的業務邏輯
		Target target1 = new Adapter();
		target1.request();
	}
}

上面這種實現的介面卡稱為類介面卡,因為 Adapter 類既繼承了 Adaptee (被適配類),也實現了 Target 介面(因為 Java 不支援多繼承,所以這樣來實現),在 Client 類中我們可以根據需要選擇並建立任一種符合需求的子類,來實現具體功能。另外一種介面卡模式是物件介面卡,它不是使用多繼承或繼承再實現的方式,而是使用直接關聯,或者稱為委託的方式。我們來看下物件介面卡的通用程式碼。

(2).物件介面卡通用程式碼:

/*
 *	目標角色
 */
interface Target {
	// 目標角色有自己的方法
	public void request();
}

/*
 * 目標角色的實現類
 */
class ConcreteTarget implements Target {

	public void request() {
		System.out.println("我是目標角色的業務邏輯");
	}
}

/*
 * 源角色
 */
class Adaptee {
	// 原有的業務邏輯
	public void doSomething() {
		System.out.println("我是被適配角色的業務邏輯");
	}
}

//介面卡類,直接關聯被適配類,同時實現標準介面
class Adapter implements Target {
	// 直接關聯被適配類
	private Adaptee adaptee;

	// 可以通過建構函式傳入具體需要適配的被適配類物件
	public Adapter(Adaptee adaptee) {
		this.adaptee = adaptee;
	}

	public void request() {
		// 這裡是使用委託的方式完成特殊功能
		this.adaptee.doSomething();
	}
}

//測試類
public class Client {
	public static void main(String[] args) {
		// 使用普通功能類
		Target concreteTarget = new ConcreteTarget();
		concreteTarget.request();

		// 使用特殊功能類,即適配類,
		// 需要先建立一個被適配類的物件作為引數
		Target adapter = new Adapter(new Adaptee());
		adapter.request();
	}
}

測試結果與上面的一致。從類圖中我們也知道需要修改的只不過就是 Adapter 類的內部結構,即 Adapter 自身必須先擁有一個被適配類的物件,再把具體的特殊功能委託給這個物件來實現。使用物件介面卡模式,可以使得 Adapter 類(適配類)根據傳入的 Adaptee 物件達到適配多個不同被適配類的功能,當然,此時我們可以為多個被適配類提取出一個介面或抽象類。這樣看起來的話,似乎物件介面卡模式更加靈活一點。

5.優點

  • 通過介面卡,客戶端可以呼叫同一介面,因而對客戶端來說是透明的。這樣做更簡單、更直接、更緊湊。
  • 複用了現存的類,解決了現存類和複用環境要求不一致的問題。
  • 將目標類和適配者類解耦,通過引入一個介面卡類重用現有的適配者類,而無需修改原有程式碼。
  • 一個物件介面卡可以把多個不同的適配者類適配到同一個目標,也就是說,同一個介面卡可以把適配者類和它的子類都適配到目標介面。
  • 靈活性好。如果某一天突然不想要介面卡了,沒問題,直接刪除這個介面卡就可以了,其他程式碼都不用修改。基本上就類似於一個靈活的構件,想用就用,不想用就解除安裝。

6.缺點

  • 類介面卡的缺點:對於java、C#等不支援多重繼承的語言,一次最多隻能適配一個適配者類,而且目標抽象類只能為介面,不能為類,其使用有一定的侷限性,不能將一個適配者類和他的子類同時適配到目標介面
  • 物件介面卡的缺點:與類介面卡模式相比,要想置換適配者類的方法就不容易。

7.適用場景

  • 想要複用一個已經存在的類,但是它卻不符合現有的介面規範,導致無法直接去訪問,這時建立一個介面卡就能間接去訪問這個類中的方法。
  • 我們有一個類,想將其設計為可重用的類(可被多處訪問),我們可以建立介面卡來將這個類來適配其他沒有提供合適介面的類。
  • 使用第三方元件,元件介面定義和自己定義的不同,不希望修改自己的介面,但是要使用第三方元件介面的功能。