介面卡和外觀模式.
一、介面卡模式
1、概念
- 定義:將一個類的介面,轉換成客戶期望的另一個類的介面,介面卡讓原本介面不相容的類可以合作無間。
- 安卓轉Type-C頭,就是一個典型的介面卡模式。在安卓頭和 Type-C 之間引入介面卡,安卓頭是被適配者。
- 解析:
1、 客戶(Client)通過目標介面(Target Interface)呼叫介面卡(Adapter)的方法對介面卡發出請求。
2、 介面卡使用被介面卡介面(Adaptee Interface)把請求轉換成被適配者的一個或多個呼叫介面。
3、 客戶接收到呼叫的結果,但並未察覺這一切是介面卡在起轉換作用。 - 結構:介面卡有兩種,分別是類介面卡和物件介面卡。類介面卡採用多重繼承實現,在 Java 中不適用;物件介面卡採用繼承和組合實現。以下是兩種結構的類圖:
2、Demo 實現
在 JDK1.0 時我們用的集合還是 Vector(後來推薦使用 ArrayList),我們用的迭代器還是 Enumeration(後來推薦使用 Iterator)。現在我們想寫一個介面卡,讓 Vector 也能使用 Iterator 迭代器,即在 Enumeration 和 Iterator 之間做適配。
/** * 1、Iterator 是目標(Target)介面角色。 * 2、Enumeration 是被適配者(Apaptee)角色。 * 3、EnumerationAdapter 是適配者(Adapter)角色。 */ public class EnumerationAdapter implements Iterator { private Enumeration enumeration; public EnumerationAdapter(Enumeration enumeration) { this.enumeration = enumeration; } @Override public boolean hasNext() { return enumeration.hasMoreElements(); } @Override public Object next() { return enumeration.nextElement(); } @Override public void remove() { throw new UnsupportedOperationException("remove"); } }
public static void main(String[] args) { Vector vector = new Vector(); vector.add("java"); vector.add("python"); vector.add("javaScript"); Enumeration enumeration = vector.elements(); Iterator iterator = new EnumerationAdapter(enumeration); while (iterator.hasNext()) { System.out.println(iterator.next()); } }
3、總結
- 應用場景:系統需要使用一些現有的類,而這些類的介面不符合系統的需要,甚至沒有這些類的原始碼。
- 優點:
1、將介面轉化成客戶真正能接受的介面,為不用的介面之間做適配。
2、客戶和被適配者之間是解耦的。倘若一段時間之後,我們想要改變介面,介面卡可以將改變的部分封裝起來,而客戶不用做任何的改變。另外,被適配者的任何子類,都可以搭配著介面卡使用。 - 缺點:
1、一次最多隻能適配一個適配者類,不能同時適配多個適配者。
2、目標抽象類只能為介面,不能為類,其使用有一定的侷限性。
二、外觀模式
- 外觀(Facade)模式:提供了一個統一的介面,用來訪問子系統中的一群介面。外觀定義了一個高層介面,讓子系統更容易使用。
- 外觀模式說是設計模式中最簡單的模式也不為過,因為它沒有那麼多複雜的角色,它的工作只有一個 —— 簡化介面。它可能持有一個或者數個類物件的組合,然後將它們複雜的一切(實現、執行順序等)隱藏在身後,只露出一個乾淨美好的外觀。
- 外觀模式不只是簡化了介面,也將客戶從元件的子系統中解耦。
- 外觀模式提供簡化介面的同時,依然將系統完整的功能暴露出來,以供需要的人使用。
三、“最少知識”原則
@Data public class Subject { private String name; }
@Data public class Teacher { private Subject subject; }
public static void main(String[] args) { Teacher teacher = new Teacher(); String name = teacher.getSubject().getName(); System.out.println(name); }
如上,我們常常這樣寫程式碼 —— teacher.getSubject().getName(),但是“最少知識”原則指導我們,應該減少物件間的間接互動:
@Data public class Teacher { private Subject subject; public String getSubjectName() { return getSubject().getName(); } }
public static void main(String[] args) { Teacher teacher = new Teacher(); String name = teacher.getSubjectName(); System.out.println(name); }
額,感覺略雞肋的用法,但是“最少知識”原則可以減少我們所依賴的類的數目。還是那句話吧,原則只是指導,具體情況具體分析。
- “最少知識”原則:減少物件之間的互動,只留下幾個“密友”。這個原則提供了一些方針:就任何物件而言,在該物件的方法內,我們只應該呼叫屬於以下範圍的方法:
1、該物件本身。
2、被當做方法的引數而傳遞進來的物件。
3、此方法所建立或例項化的任何物件。
4、物件的任何元件。 - 採用“最少知識”原則會導致更多的“包裝”類被製造出來,以處理和其他元件的溝通,這可能會導致複雜度和開發時間的增加,並降低執行時的效能。
- 所有的原則都應該在有幫助的時候才遵守。所有的設計都不免需要折衷(在抽象和速度之間取捨,在空間和時間之間平衡......)。