此模式從字面上來看應該不難理解,用現實生活中的例子來看,就好比出國時想讓自己帶的電器也能在國外用,但國外的插座孔跟電器插頭不同時要怎麼辦?有一個轉接頭就可以啦~
以程式面來看,假如你有一個系統,希望它能和一家新廠商的 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)
留言
張貼留言