一、小案例分析 1、功能需求: 以電源適配器為例。 一個人去外國旅游,住在外國某賓館,恰好手機沒電(手機是雙孔插頭),但外國賓館只有三孔插座,賓館一般不可能為了旅客,將三孔插座換成雙孔插座,此時適配器就派上用場了,將雙孔插頭轉成三孔插頭,即可滿足要求。 2、什麼是適配器模式: 適配器模式是一種結構型 ...
一、小案例分析
1、功能需求:
以電源適配器為例。
一個人去外國旅游,住在外國某賓館,恰好手機沒電(手機是雙孔插頭),但外國賓館只有三孔插座,賓館一般不可能為了旅客,將三孔插座換成雙孔插座,此時適配器就派上用場了,將雙孔插頭轉成三孔插頭,即可滿足要求。
2、什麼是適配器模式:
適配器模式是一種結構型設計模式。適配器模式的思想是:把一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠在一起工作。
3、適配器模式分類
(1)類適配器模式
(2)對象適配器模式
(3)介面適配器模式
4、適配器模式的角色:
(1)源(Adaptee):需要被適配的對象或類型,相當於雙孔插頭。
(2)適配器(Adapter):連接目標和源的中間對象,相當於插頭轉換器。
(3)目標(Target):期待得到的目標,相當於三孔插頭。
二、適配器模式
1、類適配器模式實現案例:
(1)適配器對象繼承原有類(比如三孔插頭)。
(2)適配器對象組合一個實現新介面的對象(比如雙孔插頭)。
(3)適配器原有的方法調用被委托給新介面的實例的方法。即在新介面的方法中調用原有類的方法。(使雙孔插頭可以調用三孔插頭)
(4)代碼實現:
package adapter.pattern.demo1; /** * 測試類, 測試類適配器模式 */ public class ClassAdapterDemo { public static void main(String[] args) { Adapter adapter = new Adapter(); adapter.show2(); } } /** * 三孔插頭(原有類) * */ class ThreeHolePlug { public void show1() { System.out.println("三孔插頭"); } } /** * 雙孔插頭(新需求) */ interface DoubleHolePlug { public void show2(); } /** * 繼承原有類,並實現新介面,重寫介面中的方法,並調用原有類的方法。 * */ class Adapter extends ThreeHolePlug implements DoubleHolePlug { @Override public void show2() { show1(); } }
(5)代碼分析:
採用繼承實現,使該類有一定的局限性。但是可以根據需求獲取或重寫原有類的方法。
(6)UML圖:
2、對象適配器模式實現案例
(1)適配器對象內部持有原有類的實例對象。(即三孔插口對象)
(2)適配器對象組合一個實現新介面的對象(比如雙孔插頭)。
(3)適配器原有的方法調用被委托給新介面的實例的方法。即在新介面的方法中調用原有類的方法。(使雙孔插頭可以調用三孔插頭)
(4)代碼實現:
package adapter.pattern.demo2; /** * 測試類, 測試對象適配器模式 */ public class ObjectAdapterDemo { public static void main(String[] args) { Adapter adapter = new Adapter(new ThreeHolePlug()); adapter.show2(); } } /** * 三孔插頭(原有類) * */ class ThreeHolePlug { public void show1() { System.out.println("三孔插頭"); } } /** * 雙孔插頭(新需求) */ interface DoubleHolePlug { public void show2(); } /** * 實現新介面,重寫介面中的方法,將原有類的的實例化對象放入適配器中,通過實例化對象去調用原有類的方法。 * */ class Adapter implements DoubleHolePlug { ThreeHolePlug threeHolePlug; /** * 構造器,將原有類的實例對象傳入適配器 * * @param threeHolePlug * 原有類的實例對象 */ public Adapter(ThreeHolePlug threeHolePlug) { this.threeHolePlug = threeHolePlug; } @Override public void show2() { threeHolePlug.show1(); } }
(5)代碼分析:
此段代碼,根據合成復用原則,使用聚合的方式代替繼承,降低了繼承的局限性,且不再要求新需求必須是介面。
(6)UML圖:
3、介面適配器模式(預設適配器模式):
(1)當一個介面中抽象方法過多時,實現這個類需要將所有的方法實現,不友好。可以採用一個抽象類,實現介面、重寫所有方法(將其重寫為空方法)。此時繼承抽象類,並根據需要選擇重寫的方法即可。
(2)適用於使用一個介面,卻不想重寫介面中所有方法的情景。
(3)代碼實現:
package adapter.pattern.demo3; /** * 測試類, 測試介面適配器模式 */ public class InterfaceAdapterDemo { public static void main(String[] args) { // 根據自己的需求,重寫相關方法,不需要全部重寫 new MoveApapter() { @Override public void up() { System.out.println("向上移動"); } }.up(); new MoveApapter() { @Override public void down() { System.out.println("向下移動"); } }.down(); } } /** * 介面中含有多個抽象方法 * */ interface Move { void up(); void down(); void left(); void right(); } /** * 抽象類,實現介面,並重寫所有的方法為空方法 * */ abstract class MoveApapter implements Move { @Override public void up() { } @Override public void down() { } @Override public void left() { } @Override public void right() { } }
(4)UML圖: