大衛的Design Patterns學習筆記09:Facade

一、概述
Facade(外觀)模式爲子系統中的各類(或結構與方法)提供一個簡明一致的界面,隱藏子系統的複雜性,使子系統更加容易使用。
實際應用中,我們在對付一些老舊的code(尤其是將C的代碼轉成C++代碼)或者即便不是老舊code,但涉及多個子系統時,除了重寫全部代碼(對於老舊code而言),我們還可能採用這樣一種策略:
重新進行類的設計,將原來分散在源碼中的類/結構及方法重新組合,形成新的、統一的接口,供上層應用使用。
這在某種意義上與Adapter及Proxy有類似之處,但是,Proxy(代理)注重在爲Client-Subject提供一個訪問的中間層,如CORBA可爲應用程序提供透明訪問支持,使應用程序無需去考慮平臺及網絡造成的差異及其它諸多技術細節;Adapter(適配器)注重對接口的轉換與調整;而Facade所面對的往往是多個類或其它程序單元,通過重新組合各類及程序單元,對外提供統一的接口/界面。

二、結構
Facade模式的示意圖如下:

1:Facade模式

三、應用
在遇到以下情況使用Facade模式:
1
、當你要爲一個複雜子系統提供一個簡單接口時。子系統往往因爲不斷演化而變得越來越複雜。大多數模式使用時都會產生更多更小的類。這使得子系統更具可重用性,也更容易對子系統進行定製,但這也給那些不需要定製子系統的用戶帶來一些使用上的困難。
Facade可以提供一個簡單的缺省視圖,這一視圖對大多數用戶來說已經足夠,而那些需要更多的可定製性的用戶可以越過Facade層。
2
、客戶程序與抽象類的實現部分之間存在着很大的依賴性。引入Facade將這個子系統與客戶以及其他的子系統分離,可以提高子系統的獨立性和可移植性。
3
、當你需要構建一個層次結構的子系統時,使用Facade模式定義子系統中每層的入口點,如果子系統之間是相互依賴的,你可以讓它們僅通過Facade進行通訊,從而簡化了它們之間的依賴關係。

四、優缺點
Facade模式有下面一些優點:
1
、它對客戶屏蔽子系統組件,因而減少了客戶處理的對象的數目並使得子系統使用起來更加方便。
2
、它實現了子系統與客戶之間的鬆耦合關係,而子系統內部的功能組件往往是緊耦合的。
鬆耦合關係使得子系統的組件變化不會影響到它的客戶。Facade模式有助於建立層次結構系統,也有助於對對象之間的依賴關係分層。Facade模式可以消除複雜的循環依賴關係。這一點在客戶程序與子系統是分別實現的時候尤爲重要。
在大型軟件系統中降低編譯依賴性至關重要。在子系統類改變時,希望儘量減少重編譯工作以節省時間。用Facade可以降低編譯依賴性,限制重要系統中較小的變化所需的重編譯工作。Facade模式同樣也有利於簡化系統在不同平臺之間的移植過程,因爲編譯一個子系統一般不需要編譯所有其他的子系統。
3
、如果應用需要,它並不限制它們使用子系統類。因此你可以在系統易用性和通用性之間加以選擇。

五、舉例
C++程序員經常會使用全局函數來實現一些通用方法,而Java中由於語言本身的限制,所有成員和方法都必須封裝在類中,因此,引入了很多輔助類(這些類的成員方法通常都是static的),用於提供一些相互獨立的通用方法,如java.lang.System、java.util.Arrays、java.util.Collections、javax.swing.SwingUtilities等,這些類往往也被認爲是Facade類。

以下是一個模擬的銀行抵押貸款資格審查的例子,其中的MortgageApplication類負責調用各SubSystem Class,同時對外提供統一的接口,以簡化客戶程序的操作。
#include <iostream>
#include <string>
using namespace std;

class
 Customer
{

private
:
    // Fields
    string name;

public
:
    // Constructors
    Customer( const char* name )
    {

        this
->name = name;
    }


    // Methods
    const string& getName() const
    {

        return
 name;
    }
};


// "SubSystem ClassA"
class Bank
{

public
:
    // Methods
    bool SufficientSavings( const Customer& c )
    {

        cout << "Check bank for " << c.getName().c_str() << endl;
        return
 true;
    }
};


// "SubSystem ClassB"
class Credit
{

public
:
    // Methods
    bool GoodCredit( int amount, const Customer& c )
    {

        cout << "Check credit for " << c.getName().c_str() << endl;
        return
 true;
    }
};


// "SubSystem ClassC"
class Loan
{

public
:
    // Methods
    bool GoodLoan( const Customer& c )
    {

        cout << "Check loan for " << c.getName().c_str() << endl;
        return
 true;
    }
};


// "Facade"
class MortgageApplication
{

private
:
    // Fields
    int amount;
    Bank bank;
    Loan loan;
    Credit credit;

public
:
    // Constructors
    MortgageApplication( int amount )
    {

        this
->amount = amount;
    }


    // Methods
    bool IsEligible( const Customer& c )
    {

        // Check creditworthyness of applicant
        if( !bank.SufficientSavings( c ) )
            return
 false;
        if
( !loan.GoodLoan( c ) )
            return
 false;
        if
( !credit.GoodCredit( amount, c ))
            return
 false;

        return
 true;
    }
};


/// <summary>
/// Facade Client
/// </summary>
int main()
{

    Customer customer( "Bill David" );
    // Create Facade
    MortgageApplication mortgage( 10000000 );
    // Call subsystem through Facade
    mortgage.IsEligible( customer );

    return
 0;
}


參考:
1
、http://www.dofactory.com/Patterns/PatternFacade.aspx
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章