1. 程式人生 > >設計模式學習之路

設計模式學習之路

今天瞭解一下介面卡模式。

首先, 看下需求(簡單的扯一下)。

農場有許多鴨子, 但是某天鴨子的數量不夠,正好,農場還有些火雞, 農場主打算用火雞充當鴨子。。

鴨子的介面很簡單,就兩個方法,一個呱呱叫, 一個飛。

package com.chris.adapter;

public interface Duck {
	public void quack();
	public void fly();
}

火雞的介面也很簡單,也有兩個方法, 一個咯咯叫, 一個飛(雖然會飛,但是太胖,飛的距離好短。。)

package com.chris.adapter;

public interface Turkey {
	public void gobble();
	public void fly();
}

然後,我們把農場的鴨子具體化,一種叫綠頭鴨的。。
package com.chris.adapter;

public class MallardDuck implements Duck {

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

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

}

他實現了鴨子介面,並有了具體的行為,比如叫喚,飛!

同樣, 火雞也有某個種類。。

package com.chris.adapter;

public class WildTurkey implements Turkey{

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

	@Override
	public void fly() {
		System.out.println("I'm flying a short distance");
	}
	
}
他實現了火雞介面的兩個方法, 咯咯叫以及飛很短的距離。

從介面可以看出,雖然都有兩個方法, 但是方法卻不一樣, 這樣的話, 火雞就很難偽裝成鴨子了。

所以,我們引進了介面卡模式,介面卡大家都知道,就是一個轉換插頭,比如兩孔的轉成三孔的,或者是國內標準的轉成國外的三角方插那種(出國沒有轉換頭很難受的,記得一定要帶,手機沒電不能忍。)

介面卡模式的作用也是類似的,就是將一個類的介面,轉換成客戶期望的另一個介面,讓原來介面不相容的類可以合作無間。

通過介面卡模式,我們可以通過將需要改變的介面進行封裝, 讓客戶從實現的介面中解耦。

比如,我們這邊建一個火雞介面卡的類,實現鴨子的介面。

package com.chris.adapter;

public class TurkeyAdapter implements Duck{
	Turkey turkey;
	
	public TurkeyAdapter(Turkey turkey) {
		this.turkey = turkey;
	}

	@Override
	public void quack() {
		turkey.gobble();
	}

	@Override
	public void fly() {
		for (int i = 0; i < 5; i++) {
			turkey.fly();
		}
	}

}

通過將火雞類進行包裝, 將他的實現轉換為需要實現的介面的模式,這樣,他就是一個客戶需要的介面的類了。。

我們來做下簡單的測試。

package com.chris.adapter;

public class DuckTestDrive {
	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 Duck says...");
		testDuck(turkeyAdapter);
	}

	static void testDuck(Duck duck) {
		duck.quack();
		duck.fly();
	}
}

下面貼一下測試結果(其實不貼的話,應該也猜得到結果了。。)
The Turkey says...
Gobble gobble
I'm flying a short distance

The Duck says...
Quack
I'm flying

The Duck says...
Gobble gobble
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance

都是兩種都是“鴨子”,但是具體的實現卻不一樣,這樣就完成了對期望轉變的介面的封裝。

介面卡模式充滿了良好的OO設計原則:使用物件組合, 以修改的介面包裝被適配者,將客戶和介面繫結起來,而不是具體的實現,也是一個值得遵循的地方。

實際上,介面卡還可以細分為物件介面卡和類介面卡, 他們的區別就是,物件介面卡是用的組合的方式,而類介面卡是用的繼承, 但是由於java是不能多繼承的,所以類介面卡不適用的, 一般關注物件介面卡就行了。

在平時的開發過程中, 介面卡的用法還是不多的。

如果在單元測試中,需要呼叫到第三方的類,但是又需要繞過他的呼叫的時候,往往可以用介面卡模式對他進行包裝, 用stub進行單元測試, 避免了第三方的呼叫的耗時。

在一個新的專案開始的時候,介面卡模式幾乎就不怎麼用了,而是在後續進行重構或者維護的時候,為了避免對程式碼的大改,可以巧妙的多用介面卡模式,對類進行包裝,從而優雅的完成重構。

書中的例子都是Head First設計模式中(我要安利一下這本書,很好!!)的,但是都是我手敲的(沒有功勞也有苦勞),如果在文中有什麼錯誤的理解或者遺漏,還希望大家多多指導,共勉!!