外观模式【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() 便可成功订餐!

以上。

相关文章
相关标签/搜索