HeadFirst設計模式(七) - 適配器模式

咱們周圍的適配器

    OO適配器是什麼,必定不難理解,由於現實中處處都是。比方說:若是你須要一個兩項插頭,但牆上只有一個三項插座,這時候你就須要使用一個交流電的適配器……java

    又或者你須要對經過串口對某設備進行調試,可是你的機器沒有串口,只有USB接口,這時候你就須要一個USB轉串口的適配器……測試

    這是真實世界的適配器,那面向對象適配器又是什麼?其實,OO適配器和真實世界的適配器扮演着一樣的角色:將一個接口轉換成另外一個接口,以符合客戶的指望。this

面向對象適配器

    假設已有一個軟件系統,它與舊廠商的某個接口搭配使用。你但願替換掉舊廠商,讓它能和一個新廠商類庫搭配使用,可是這個新廠商所設計出來的接口,不一樣於舊廠商的接口。你不想改變現有的代碼解決這個問題。因此須要編寫一個適配器,這個適配器工做起來就如同一箇中間人,它將客戶所發出的請求轉換成新廠商能理解的請求。spa

舉個例子

    以鴨子類爲例,鴨子能夠飛,而且能夠呱呱叫,如下是鴨子類的接口與實現:設計

public interface Duck {
	// 呱呱叫
	public void quack();
	// 飛
	public void fly();
}

public class MallardDuck implements Duck {

	public void quack() {
		System.out.println("Quack");
	}

	public void fly() {
		System.out.println("I'm flying");
	}

}

    接下來再看一個「街頭頑禽」火雞類的接口和實現類:調試

public interface Turkey {
	// 火雞不會呱呱叫,只會咯咯叫
	public void gobble();
	// 夥計會飛,雖然飛不遠
	public void fly();
}

public class WildTurkey implements Turkey {

	public void gobble() {
		System.out.println("Gobble gobble");
	}

	public void fly() {
		System.out.println("I'm flying a short distance");
	}

}

    如今,假設你缺鴨子對象,想用一些火雞對象冒充。顯而易見,由於火雞的接口不一樣,因此咱們不能公然拿來用。 因此就須要寫一個適配器。code

    也就是說,加入你有一個方法,參數是Duck接口,你想把Turkey接口傳遞進去。對象

    接下來適配器的代碼:接口

// 首先,適配器須要實現想轉換成的接口類型。
// 這裏想把火雞轉換成鴨子,因此實現了鴨子的接口。
public class TurkeyAdapter implements Duck {

	Turkey turkey;

	// 接着,須要取得要適配的對象引用。
	// 也就是你的客戶所指望看到的接口。
	// 這裏想把火雞轉換成鴨子,因此傳入火雞的接口。
	public TurkeyAdapter(Turkey turkey) {
		this.turkey = turkey;
	}

	// 在鴨子叫的方法中調用火雞叫的方法。
	public void quack() {
		turkey.gobble();
	}

	// 在鴨子飛的方法中調用火雞飛的方法。
	// 由於火雞飛不遠,鴨子飛一次,火雞須要飛五次。
	public void fly() {
		for (int i = 0; i < 5; i++) {
			turkey.fly();
		}
	}

}

    測試適配器:get

public class Client {

	public static void main(String[] args) {
		// 建立一隻鴨子
		MallardDuck duck = new MallardDuck();
		// 建立一直火雞
		WildTurkey turkey = new WildTurkey();
		
		// 將火雞包裝進一個火雞適配器,是它看起來像是一隻鴨子。
		Duck turkeyAdapter = new TurkeyAdapter(turkey);
		
		System.out.println("The Turkey says...");
		turkey.gobble();
		turkey.fly();
		
		System.out.println("\nThe Duck says...");
		testDuck(duck);
		
		System.out.println("\nThe TurkeyAdapter says...");
		testDuck(turkeyAdapter);
	}
	
	static void testDuck(Duck duck) {
		duck.quack();
		duck.fly();
	}
	
}

    首先讓火雞又叫又飛,接着讓鴨子又叫又飛,最後讓適配器處理過的火雞像鴨子同樣又叫又飛,quack()被調用時,適配器咯咯叫。testDuck()方法根本不知道,這實際上是一隻僞裝成鴨子的火雞!

適配器模式解析

    如今咱們已經知道什麼是適配器了,讓咱們退後一步,再次看看各部分之間的關係。‘

    客戶端調用適配器的過程以下:

  1. 客戶經過目標接口調用適配器的方法對適配器發出請求;
  2. 適配器使用被適配者接口吧請求轉換成被適配者的一個或多個調用接口;
  3. 客戶接收到調用的結果,但並未察覺這一切是適配器在起轉換做用;

    如今來看看適配器模式的類圖:

    這個適配器模式充滿良好的OO設計原則:使用對象組合,以修改的接口包裝被適配者,這種作法還有額外的優勢,那就是,被適配者的任何子類,均可以搭配着適配器使用。

    在上面的類圖中,鴨子類就是Target類,火雞類就是Adaptee類。

    以上就是適配器模式。

相關文章
相關標籤/搜索