此模式從字面上來看應該不難理解,用現實生活中的例子來看,就好比出國時想讓自己帶的電器也能在國外用,但國外的插座孔跟電器插頭不同時要怎麼辦?有一個轉接頭就可以啦~
以程式面來看,假如你有一個系統,希望它能和一家新廠商的 library 搭配使用,但新廠商的介面卻不同於舊廠商的介面。當不能或不想修改現有的程式碼時,就可以寫一個類別,將新廠商的介面轉換成你所希望的介面。
接下來看點程式碼吧。這裡使用策略模式中使用的鴨子類別,並新增一組火雞類別:
當你想用火雞物件來假裝成鴨子物件,四筒扮五筒,很明顯因為兩邊介面不同不能直接用時,就寫個轉接器吧:
以程式面來看,假如你有一個系統,希望它能和一家新廠商的 library 搭配使用,但新廠商的介面卻不同於舊廠商的介面。當不能或不想修改現有的程式碼時,就可以寫一個類別,將新廠商的介面轉換成你所希望的介面。
接下來看點程式碼吧。這裡使用策略模式中使用的鴨子類別,並新增一組火雞類別:
// 鴨子介面
public interface Duck {
public void quack();
public void fly();
}
// 綠頭鴨是鴨子的次類別
public class MallardDuck implements Duck {
@Override
public void quack()
{
System.out.println("Quack");
}
@Override
public void fly()
{
System.out.println("I'm flying");
}
}
// 火雞介面
public interface Turkey {
// 火雞只會喀喀叫
public void gobble();
public void fly();
}
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");
}
}
// 轉接器要實作要轉換的型態,
// 也就是你的客戶所希望看到的介面
public class TurkeyAdapter implements Duck {
private Turkey mTurkey;
// 需要取得被轉換者的物件參考
// 範例是利用建構者取得
public TurkeyAdapter(Turkey turkey)
{
mTurkey = turkey;
}
// 實作介面的方法,並把方法都導向
// 使用被轉接者提供的方法
@Override
public void quack()
{
mTurkey.gobble();
}
@Override
public void fly()
{
mTurkey.fly();
}
}
從上述的程式碼,我們可以理解:- 客戶透過目標介面 (Duck) 呼叫轉接器的方法,如 TurkeyAdapter.fly(),對轉接器發出要求。
- 轉接器透過被轉接者介面 (Turkey),呼叫被轉接者的方法,將請求轉給被轉接者。
- 客戶接收到呼叫的結果,不會發現這一切都是透過轉接器居中聯繫。
轉接器模式將一個類別的介面,轉換成別一個介面以供客戶使用。轉接器讓原本介面不相容的類別可以合作無間。
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.
此模式充滿著良好的 OO 設計守則:檢查使用的物件合成,並以修改的介面包裝被轉接者。這種作法還有額外的優點,就是被轉接者的任何次類別,都可以搭配轉接器使用。要注意,此模式是建立客戶和介面之間的關係,不是建立客戶和實作內容的關係。
其實轉接器可以有兩種模式:「物件」轉接器跟「類別」轉接器,上面看到的是物件轉接器。而類別轉接器需要多重繼承才能實作它,雖然在 Java 中不可能實作類別轉接器,但我們還是能看看它的類別圖:
其中主要的差異就是利用繼承被轉接者和目標類別,設計出類別轉接器。
參考資料:
深入淺出設計模式(Head First Design Patterns)
深入淺出設計模式(Head First Design Patterns)


留言
張貼留言