外觀模式【C#】

示例代碼爲了儘量突顯設計模式的特徵,採用了極簡代碼。儘可能避免其餘代碼對理解設計模式產生干擾

定義

爲子系統中的一組接口提供一個一致的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
簡而言之就是,外觀模式可使客戶端不用關心各個子系統之間的交互邏輯,它只須要知道擔任「外觀角色」的接口是哪一個就足夠了。

結構導圖(劉偉老師的博客

外觀模式結構導圖


代碼

場景1

某個週六臨近中午時,小明餓了!爲了填飽肚子,他只能從牀上爬起來,準備作飯。
要知道,這可不是件容易的事情!畢竟本身作飯的話,須要先去菜市場買菜,洗菜,而後才能作菜。起碼也得折騰一小時,才能吃上飯!
雖然很不情願,但別無選擇!c#

class BuyVegetables
{
    /// <summary>
    /// 買菜
    /// </summary>
    public static void Buy()
    {
        Console.WriteLine("買完食材了。");
    }
}
class Cleanout
{
    /// <summary>
    /// 洗菜
    /// </summary>
    public static void Clean()
    {
        Console.WriteLine("該洗的菜都洗好了。");
    }
}
class Cooking
{
    /// <summary>
    /// 作菜
    /// </summary>
    public static void Cook()
    {
        Console.WriteLine("飯菜作好了。");
    }
}

該忙的都忙完了,能夠開飯了!設計模式

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("該吃飯了···");
        BuyVegetables.Buy();
        Cleanout.Clean();
        Cooking.Cook();
        Console.WriteLine("吃飽喝足。");
    }
}

運行結果

這頓飯還真是把小明折騰慘了!!!spa

場景2

一週過去了···.net

又到了週六,又到了臨近中午的時間點,小明又餓了···
多麼似曾相識的一幕~~~
但今天他實在不想再作飯了,因此,他選擇了訂外賣!!!設計

不過,想訂外賣,首先得有餐館的聯繫方式。
這個訂餐服務其實就充當了外觀者的邏輯入口。code

class Restaurant
{
    /// <summary>
    /// 外賣服務
    /// </summary>
    public static void Order()
    {
        Console.WriteLine("已收到訂單,正在出餐···");
        BuyVegetables.Buy();
        Cleanout.Clean();
        Cooking.Cook();
        Console.WriteLine("已出餐,正在配送中···");
    }
}

有了餐館的聯繫方式後,就簡單了。中間件

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("該吃飯了,點個外賣吧···");
        Restaurant.Order();
        Console.WriteLine("收到外賣,開飯!");
        Console.WriteLine("吃飽喝足,順便還打了個飽嗝···");
    }
}

運行結果

此次可輕鬆了。blog

總結

場景1中,客戶(小明)與吃飯這件事的交互至關麻煩,整個流程他本身作下來要費很多心思!實際工做中,這種場景很是常見,每一次都把子系統的邏輯耦合到客戶端內,那麼客戶端將變得至關臃腫,且不穩定。
此時,提供一箇中間件(外觀者),也就是場景2中的「餐館」,這樣的話,小明只要一個電話,買菜,洗菜,作菜這種事情就都有人幫他解決了。實際工做中,也能夠提供一個外觀者,由它來負責和各個子系統(或者子功能)的交互。這個外觀者對客戶端提供一個入口方法,而客戶端只須要調用這個入口方法,就能夠把全部想作的事情所有處理掉,這樣勢必會減輕客戶端的複雜度。接口

補充討論

若是某一天,小明只是隨便點了一份清湯麪,這樣的話餐館就不用洗菜,只須要買麪條,而且煮好送到小明的手裏就行了。那怎麼辦呢?難道要改外觀者的代碼,把裏面的Cleanout.Clean();代碼刪掉?這豈不是違反了開閉原則?
是的,若是這樣處理,那麼勢必會違反開閉原則!get

怎麼辦呢?此時能夠把外觀者角色抽象出來!

interface IRestaurant
{
    /// <summary>
    /// 訂餐服務
    /// </summary>
    void Order();
}

而後實現一個具體外觀者-麪館。

class NoodleRestaurant : IRestaurant
{
    public void Order()
    {
        Console.WriteLine("已收到訂單,正在出餐···");
        BuyVegetables.Buy();
        Cooking.Cook();
        Console.WriteLine("已出餐,正在配送中···");
    }
}

這樣小明只須要在想吃麪的時候,使用new NoodleRestaurant().Order() 便可成功訂餐!

以上。

相關文章
相關標籤/搜索