设计模式(9)装饰器模式

模式介绍

装饰器模式试图向现有对象添加新的功能,而不改变该对象的定义。
换句话说,它希望向对象的单个实例添加新的职责,而不向对象类添加这些职责。

示例

想象一下,我们在一个farm-to-table餐馆。这个餐馆只售卖来自农场种植的蔬菜。但是有的时候,某种蔬菜暂时没有了,我们需要通知用户。

我们来模拟一下:

首先我们创建菜肴

/// <summary>
/// The abstract Component class
/// </summary>
abstract class RestaurantDish
{
    public abstract void Display();
}

具体的菜肴实现(沙拉与面食)

/// <summary>
/// A ConcreteComponent class
/// </summary>
class FreshSalad : RestaurantDish
{
    private string _greens;
    private string _cheese; //I am going to use this pun everywhere I can
    private string _dressing;

    public FreshSalad(string greens, string cheese, string dressing)
    {
        _greens = greens;
        _cheese = cheese;
        _dressing = dressing;
    }

    public override void Display()
    {
        Console.WriteLine("\nFresh Salad:");
        Console.WriteLine(" Greens: {0}", _greens);
        Console.WriteLine(" Cheese: {0}", _cheese);
        Console.WriteLine(" Dressing: {0}", _dressing);
    }
}

/// <summary>
/// A ConcreteComponent class
/// </summary>
class Pasta : RestaurantDish
{
    private string _pastaType;
    private string _sauce;

    public Pasta(string pastaType, string sauce)
    {
        _pastaType = pastaType;
        _sauce = sauce;
    }

    public override void Display()
    {
        Console.WriteLine("\nClassic Pasta:");
        Console.WriteLine(" Pasta: {0}", _pastaType);
        Console.WriteLine(" Sauce: {0}", _sauce);
    }
}

构建一个装饰器类

/// <summary>
/// The abstract Decorator class.  
/// </summary>
abstract class Decorator : RestaurantDish
{
    protected RestaurantDish _dish;

    public Decorator(RestaurantDish dish)
    {
        _dish = dish;
    }

    public override void Display()
    {
        _dish.Display();
    }
}

具体的装饰器实现

/// <summary>
/// A ConcreteDecorator. This class will impart "responsibilities" onto the dishes 
/// (e.g. whether or not those dishes have enough ingredients left to order them)
/// </summary>
class Available : Decorator
{
    public int NumAvailable { get; set; } //How many can we make?
    protected List<string> customers = new List<string>();
    public Available(RestaurantDish dish, int numAvailable) : base(dish)
    {
            NumAvailable = numAvailable;
    }

    public void OrderItem(string name)
    {
        if (NumAvailable > 0)
        {
            customers.Add(name);
            NumAvailable--;
        }
        else
        {
            Console.WriteLine("\nNot enough ingredients for " + name + "'s order!");
        }
    }

    public override void Display()
    {
        base.Display();

        foreach(var customer in customers)
        {
            Console.WriteLine("Ordered by " + customer);
        }
    }
}

客户端调用:

static void Main(string[] args)
{
    //Step 1: Define some dishes, and how many of each we can make
    FreshSalad caesarSalad = new FreshSalad("Crisp romaine lettuce", "Freshly-grated Parmesan cheese", "House-made Caesar dressing");
    caesarSalad.Display();

    Pasta fettuccineAlfredo = new Pasta("Fresh-made daily pasta", "Creamly garlic alfredo sauce");
    fettuccineAlfredo.Display();

    Console.WriteLine("\nMaking these dishes available.");

    //Step 2: Decorate the dishes; now if we attempt to order them once we're out of ingredients, we can notify the customer
    Available caesarAvailable = new Available(caesarSalad, 3);
    Available alfredoAvailable = new Available(fettuccineAlfredo, 4);

    //Step 3: Order a bunch of dishes
    caesarAvailable.OrderItem("John");
    caesarAvailable.OrderItem("Sally");
    caesarAvailable.OrderItem("Manush");

    alfredoAvailable.OrderItem("Sally");
    alfredoAvailable.OrderItem("Francis");
    alfredoAvailable.OrderItem("Venkat");
    alfredoAvailable.OrderItem("Diana");
    alfredoAvailable.OrderItem("Dennis"); //There won't be enough for this order.

    caesarAvailable.Display();
    alfredoAvailable.Display();

    Console.ReadKey();
}

总结

装饰器模式试图在运行时动态地向对象的实例添加功能,而不需要更改实例类的定义。
这对于某些场景特别有用,比如同一对象的不同实例可能表现不同的行为。

源代码

https://github.com/exceptionnotfound/DesignPatterns/tree/master/Decorator

原文

https://www.exceptionnotfound.net/decorator-the-daily-design-pattern/

猜你喜欢

转载自www.cnblogs.com/talentzemin/p/9848080.html
今日推荐