這篇文章帶給大家的內容是Java中適配器模式(Adapter)是什麼?適配器模式(詳解)。有一定的參考價值,有需要的朋友可以參考一下,希望對你們有幫助。
目的:把來源類型適配為目標類型,以適應客戶端(Client)的需求;這裡我們把目標介面的呼叫方視為客戶端
使用場景:需要對類型進行由來源類型轉換到目標類型的場景中
前置條件:已有客戶端
//Client 一个调用目标接口的方法 Class ClientInvoking { static void invoke(TargetInterface target) { String value = target.getMark(); System.out.println(value); } }
常用的幾種模式
模式一:存在目標接口,且存在已有方法
//目标接口 public interface TargetInterface { public String getMark(); public String getInfo(); }
//已有类及方法 public class ExistClass { public String sayHello() { return "Hello"; } public String sayWorld() { return "World"; } }
我們假設ExistClass返回的字串正好是我們的客戶端需要用到的,但客戶端需要的是透過一個TargetInterface類型的物件來獲取,因此我們需要想辦法對已有類別進行適配,使其能夠滿足客戶端的需求;該模式下存在兩種應用方案:
#方案1.類別適配器模式
//适配器 public class ClassAdapter extends ExistClass implements TargetInterface { public int getMark() { String value = this.sayHello(); return value; } public int getInfo() { String value = this.sayWorld(); return value; } }
//客户端调用 TargetInterface target = new ClassAdapter(); ClientInvoking.invoke(target);
由Java介面的概念可知,ClassAdapter作為TargetInterface的實作類,能夠向上轉型為TargetInterface類型,適應了客戶端的需求。
方案2.物件適配器模式
//适配器 public class ClassAdapter implements TargetInterface { private ExistClass exist; public ClassAdapter(ExistClass existClass) { this.exist = existClass; } public int getMark() { String value = exist.sayHello(); return value; } public int getInfo() { String value = exist.sayWorld(); return value; } }
//客户端调用 TargetInterface target = new ClassAdapter(new ExistClass()); ClientInvoking.invoke(target);
此方案與類別適配器模式類似,只是不採用繼承而採用持有物件的方式,更加靈活,擴展性更強。
模式二:不存在目標接口,但是存在目標類,且存在已有方法
我們先對前置條件中的客戶端進行改造,如下:
Class ClientInvoking { static void invoke(TargetClass target) { String value = target.getMark(); System.out.println(value); } }
改造後,invoke方法需要一個TargetClass類別的物件作為參數;下面是目標類別和已有類別
//目标类 public class Class { public String getMark() { return "yes"; } public String getInfo() { return "no"; } }
//已有类及方法 public class ExistClass { public String sayHello() { return "Hello"; } public String sayWorld() { return "World"; } }
我們假設ExistClass回傳的字串剛好是我們的客戶端需要用到的,且客戶端中需要的TargetClass物件的內容已經過時,因此我們需要相辦法對ExistClass進行適配,以適應客戶端的需求;
//适配器 public class ClassAdapter extends TargetClass { private ExistClass exist; public ClassAdapter(ExistClass existClass) { this.exist = existClass; } public int getMark() { String value = exist.sayHello(); return value; } public int getInfo() { String value = exist.sayWorld(); return value; } }
//客户端调用 TargetClass target = new ClassAdapter(new ExistClass()); ClientInvoking.invoke(target);
在該種模式下,設計到兩個類,且最後要進行向上轉型,根據Java的單繼承機制,我們只能透過持有物件的形式,即物件適配器模式。
模式三:預設適配器模式
該模式中,不存在明確的目標類型,而僅有來源類型;之所以需要用到這個,往往是因為來源類型中提供了太多我們並不需要的東西,我們需要透過適配器模式進行客製化。以WindowListener作為例子講解:
//WindowListener源码 public interface WindowListener extends EventListener { public void windowOpened(WindowEvent e); public void windowClosing(WindowEvent e); public void windowClosed(WindowEvent e); ... }
//添加监听器的例子 Frame frame = new Frame(); frame.addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { } @Override public void windowClosing(WindowEvent e) { } @Override public void windowClosed(WindowEvent e) { } ... })
這樣的程式碼,看起來很繁瑣;比如說我只需要監聽正在關閉的事件,卻產生了許多與此無關的模板程式碼,降低了程式碼的可讀性,鑑於此,我們來做下定制,只監聽一個接口;
我們首先提供一個抽象類別實現了該接口,並為所有監聽器提供空實現;然後再用抽象類別的子類別重寫視窗正在關閉的監聽器的實現,程式碼如下:
//适配器 public abstract ListenerAdapter implements WindowListener { public void windowOpened(WindowEvent e) {} public void windowClosing(WindowEvent e) {} public void windowClosed(WindowEvent e) {} ... }
//重写方法 public class OverrideWindowClosing extends ListenerAdapter { @Override public void windowClosing(WindowEvent e) { //TODO } }
//客户端调用 frame.addWindowListener(new OverrideWindowClosing());
該方式簡化了接口,提高了程式碼可讀性。最重要的是,我們實現了對介面的定制,可以只做自己關心的事情。
總結:以上就是這篇文章的全部內容,希望能對大家的學習有所幫助。更多相關教學請造訪Java影片教學,java開發圖文教學,bootstrap影片教學!
以上是Java中適配器模式(Adapter)是什麼?適配器模式(詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!