1. 概述
外觀模式通過外觀的包裝,使複雜的系統對外只能看到外觀物件,而不會看到具體的細節物件,為子系統中的一組介面提供了一個統一的訪問介面,這個介面使得子系統更容易被訪問或者使用。 這樣無疑會降低應用程式的複雜度,並且提高了程式的可維護性。
2. 組成
為子系統中的一組介面提供一個一致的介面, Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。引入外觀角色之後,使用者只需要直接與外觀角色互動,使用者與子系統之間的複雜關係由外觀角色來實現,從而降低了系統的耦合度。
其組成如下:
- 外觀角色(Facade):是核心,他被客戶client角色呼叫,知道各個子系統的功能。同時根據客戶角色已有的需求預訂了幾種功能組合。
- 子系統角色(Subsystem classes):實現子系統的功能,並處理由Facade物件指派的任務。對子系統而言,facade和client角色是未知的,沒有Facade的任何相關資訊;即沒有指向Facade的例項。
- 客戶角色(client):呼叫facade角色獲得完成相應的功能。
3. 示例
3.1 子系統
//子系統A
public class SubSystemOne
{
public void MethodeOne()
{
System.out.println("Sub System A method.");
}
}
// 子系統B
public class SubSystemTwo
{
public void MethodTwo()
{
System.out.println("Sub System B method.");
}
}
// 子系統C
public class SubSystemThree
{
public void MethodThree()
{
System.out.println("Sub System C method.");
}
}
複製程式碼
一共有三個子系統,每個子系統都有自己的方法。
3.2 外觀類
// 外觀類
public class Facade
{
private SubSystemOne one;
private SubSystemTwo two;
private SubSystemThree three;
public Facade()
{
one = new SubSystemOne();
two = new SubSystemTwo();
three = new SubSystemThree();
}
public void MethodA()
{
System.out.println("\nMethod group A----");
one.MethodeOne();
two.MethodTwo();
}
public void MethodB()
{
System.out.println("\nMethod group B----");
two.MethodTwo();
three.MethodThree();
}
}
複製程式碼
外觀類是提供給客戶端呼叫直接進行呼叫,外觀類對子系統提供的方法進行組合,形成兩個組,分別表現為不同的行為(呼叫不同的方法)。
3.3 客戶端
public class FacadeTest
{
public static void main(string[] args)
{
// 呼叫外觀類
Facade facade = new Facade();
facade.MethodA();
facade.MethodB();
}
}
複製程式碼
由於Facade的作用,客戶端可以根本不知道子系統類的存在。
4. 場景和優缺點
4.1 使用場景
- 當你要為一個複雜子系統提供一個簡單介面時。子系統往往因為不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。 這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的使用者帶來一些使用上的困難。facade可以提供一個簡單的預設檢視, 這一檢視對大多數使用者來說已經足夠,而那些需要更多的可定製性的使用者可以越過facade層。
- 客戶程式與抽象類的實現部分之間存在著很大的依賴性。引入 facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性 和可移植性。
- 當你需要構建一個層次結構的子系統時,使用 facade模式定義子系統中每層的入口點。如果子系統之間是相互依賴的,你可以讓它們僅通過facade進行通訊,從而簡化了它們之間的依賴關係。
4.2 優點
- Facade模式降低了客戶端對子系統使用的複雜性。
- 外觀模式鬆散了客戶端與子系統的耦合關係,讓子系統內部的模組能更容易擴充套件和維護。
- 通過合理使用Facade,可以幫助我們更好的劃分訪問的層次。
4.3 缺點
- 不能很好地限制客戶使用子系統類,如果對客戶訪問子系統類做太多的限制則減少了可變性和靈活性。
- 在不引入抽象外觀類的情況下,增加新的子系統可能需要修改外觀類或客戶端的原始碼,違背了“開閉原則”。
5. 總結
本文主要講了設計模式的外觀模式,從概述到組成,以一個例項進行講解各個組成角色,最後概括了使用場景和外觀模式的優缺點。外觀模式的思路,有點讓人聯想其介面卡模式,介面卡模式是將一個介面通過適配來間接轉換為另一個介面。而外觀模式,其主要是提供一個整潔的一致的介面給客戶端。
外觀模式要求一個子系統的外部與其內部的通訊通過一個統一的外觀物件進行,外觀類將客戶端與子系統的內部複雜性分隔開,使得客戶端只需要與外觀物件打交道,而不需要與子系統內部的很多物件打交道。從很大程度上提高了客戶端使用的便捷性,使得客戶端無須關心子系統的工作細節,通過外觀角色即可呼叫相關功能。
另外,不要試圖通過外觀類為子系統增加新行為,不要通過繼承一個外觀類在子系統中加入新的行為,這種做法是錯誤的。外觀模式的用意是為子系統提供一個集中化和簡化的溝通渠道,而不是向子系統加入新的行為,新的行為的增加應該通過修改原有子系統類或增加新的子系統類來實現,不能通過外觀類來實現。