1. 程式人生 > >外觀(Facade)模式

外觀(Facade)模式

什麼是(Facade)模式?

    Facade(外觀)模式為子系統中的各類(或結構與方法)提供一個簡明一致的介面,隱藏子系統的複雜性,使子系統更加容易使用(出自百度文庫)。即當子系統複雜或者繁鎖時,我們讓子系統提供一個視窗,程式中稱為介面,其它程式或者物件就通過這個視窗(介面)與此子系統聯絡。介面可以是類或方法等。這樣就簡化了子系統的使用。

作用是什麼?

   簡化子系統的使用。

如何實現?

   當子系統(或者物件)使用很複雜時,我們建立一個介面(視窗)物件,將子系統的複雜的使用方法寫在此象中,其它物件或程式通過呼叫此介面(視窗)來使用系統。即在其它物件或程式中加了一層,此層用於呼叫子系統。而其它物件使用些層來呼叫子系統,而不管此層如何呼叫子系統。

概述

   在軟體開發系統中,客戶程式經常會與複雜系統的內部子系統之間產生耦合,而導致客戶程式隨著子系統的變化而變化。那麼如何簡化客戶程式與子系統之間的互動介面?如何將複雜系統的內部子系統與客戶程式之間的依賴解耦?這就是要說的Façade 模式。


意圖

   為子系統中的一組介面提供一個一致的介面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。[GOF 《設計模式》]

示意圖

   門面模式沒有一個一般化的類圖描述,下面是一個示意性的物件圖:

1 Façade模式示意性物件圖

生活中的例子

  外觀模式為子系統中的介面定義了一個統一的更高層次的介面,以便於使用。當消費者按照目錄採購時,則體現了一個外觀模式。消費者撥打一個號碼與客服代表聯絡,客服代表則扮演了這個

"外觀",他包含了與訂貨部、收銀部和送貨部的介面。

2使用電話訂貨例子的外觀模式物件圖

Facade模式解說

    我們平時的開發中其實已經不知不覺的在用Façade模式,現在來考慮這樣一個抵押系統,當有一個客戶來時,有如下幾件事情需要確認:到銀行子系統查詢他是否有足夠多的存款,到信用子系統查詢他是否有良好的信用,到貸款子系統查詢他有無貸款劣跡。只有這三個子系統都通過時才可進行抵押。我們先不考慮Façade模式,那麼客戶程式就要直接訪問這些子系統,分別進行判斷。類結構圖下:

3

在這個程式中,我們首先要有一個顧客類,它是一個純資料類,並無任何操作,示意程式碼:

//顧客類

public class Customer
設計模式--(Facade)模式{
    private string _name;

    public Customer(string name)
設計模式--(Facade)模式    {
        this._name = name;
    }


    public string Name
設計模式--(Facade)模式    {
設計模式--(Facade)模式        get return _name; }
    }

}


下面這三個類均是子系統類,示意程式碼:

//銀行子系統
public class Bank
設計模式--(Facade)模式{
    public bool HasSufficientSavings(Customer c, int amount)
設計模式--(Facade)模式    {
        Console.WriteLine("Check bank for " + c.Name);
        return true;
    }

}


//信用子系統
public class Credit
設計模式--(Facade)模式{
    public bool HasGoodCredit(Customer c)
設計模式--(Facade)模式    {
        Console.WriteLine("Check credit for " + c.Name);
        return true;
    }

}


//貸款子系統
public class Loan
設計模式--(Facade)模式{
    public bool HasNoBadLoans(Customer c)
設計模式--(Facade)模式    {
        Console.WriteLine("Check loans for " + c.Name);
        return true;
    }

}

來看客戶程式的呼叫:

//客戶程式
public class MainApp
設計模式--(Facade)模式{
    private const int _amount = 12000;

    public static void Main()
設計模式--(Facade)模式    {
        Bank bank = new Bank();
        Loan loan = new Loan();
        Credit credit = new Credit();

        Customer customer = new Customer("Ann McKinsey");

        bool eligible = true;

        if (!bank.HasSufficientSavings(customer, _amount))
設計模式--(Facade)模式        {
            eligible = false;
        }

        else if (!loan.HasNoBadLoans(customer))
設計模式--(Facade)模式        {
            eligible = false;
        }

        else if (!credit.HasGoodCredit(customer))
設計模式--(Facade)模式        {
            eligible = false;
        }


        Console.WriteLine("\n" + customer.Name + " has been " + (eligible ? "Approved" : "Rejected"));
        Console.ReadLine();
    }

}

  可以看到,在不用Façade模式的情況下,客戶程式與三個子系統都發生了耦合,這種耦合使得客戶程式依賴於子系統,當子系統變化時,客戶程式也將面臨很多變化的挑戰。一個合情合理的設計就是為這些子系統建立一個統一的介面,這個介面簡化了客戶程式的判斷操作。看一下引入Façade模式後的類結構圖:

4

門面類Mortage的實現如下:

//外觀類
public class Mortgage
設計模式--(Facade)模式{
    private Bank bank = new Bank();
    private Loan loan = new Loan();
    private Credit credit = new Credit();

    public bool IsEligible(Customer cust, int amount)
設計模式--(Facade)模式    {
        Console.WriteLine("{0} applies for {1:C} loan\n",
          cust.Name, amount);

        bool eligible = true;

        if (!bank.HasSufficientSavings(cust, amount))
設計模式--(Facade)模式        {
            eligible = false;
        }

        else if (!loan.HasNoBadLoans(cust))
設計模式--(Facade)模式        {
            eligible = false;
        }

        else if (!credit.HasGoodCredit(cust))
設計模式--(Facade)模式        {
            eligible = false;
        }


        return eligible;
    }

}


顧客類和子系統類的實現仍然如下:

//銀行子系統
public class Bank
設計模式--(Facade)模式{
    public bool HasSufficientSavings(Customer c, int amount)
設計模式--(Facade)模式    {
        Console.WriteLine("Check bank for " + c.Name);
        return true;
    }

}


//信用證子系統
public class Credit
設計模式--(Facade)模式{
    public bool HasGoodCredit(Customer c)
設計模式--(Facade)模式    {
        Console.WriteLine("Check credit for " + c.Name);
        return true;
    }

}


//貸款子系統
public class Loan
設計模式--(Facade)模式{
    public bool HasNoBadLoans(Customer c)
設計模式--(Facade)模式    {
        Console.WriteLine("Check loans for " + c.Name);
        return true;
    }

}


//顧客類
public class Customer
設計模式--(Facade)模式{
    private string name;

    public Customer(string name)
設計模式--(Facade)模式    {
        this.name = name;
    }


    public string Name
設計模式--(Facade)模式    {
設計模式--(Facade)模式        get return name; }
    }

}

而此時客戶程式的實現:

//客戶程式類
public class MainApp
設計模式--(Facade)模式{
    public static void Main()
設計模式--(Facade)模式    {
        //外觀
        Mortgage mortgage = new Mortgage();

        Customer customer = new Customer("Ann McKinsey");
        bool eligable = mortgage.IsEligible(customer, 125000);

        Console.WriteLine("\n" + customer.Name +
            " has been " + (eligable ? "Approved" : "Rejected")); 
        Console.ReadLine();
    }