設計模式學習之路
今天瞭解一下介面卡模式。
首先, 看下需求(簡單的扯一下)。
農場有許多鴨子, 但是某天鴨子的數量不夠,正好,農場還有些火雞, 農場主打算用火雞充當鴨子。。
鴨子的介面很簡單,就兩個方法,一個呱呱叫, 一個飛。
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設計模式中(我要安利一下這本書,很好!!)的,但是都是我手敲的(沒有功勞也有苦勞),如果在文中有什麼錯誤的理解或者遺漏,還希望大家多多指導,共勉!!