zoukankan      html  css  js  c++  java
  • 设计模式(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("
    Fresh 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("
    Classic 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("
    Not 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("
    Making 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/

  • 相关阅读:
    EasyUI-datagrid-自动合并单元格(转)
    js中格式化时间字符串
    ext 3.2 tree 在IE10中点击事件失效的bug
    C#中修改Dll文件 (反编译后重新编译)
    GridView内容<br />换行
    使用Aspose.Words把 word转成图片
    判断移动设备访问自动跳转到移动版页面
    jquery mobile界面数据刷新
    Ubuntu16.04下安装Visual Studio Code
    npm 安装vue 报错Failed at the chromedriver@2.46.0 install script 'node install.js'
  • 原文地址:https://www.cnblogs.com/talentzemin/p/9848080.html
Copyright © 2011-2022 走看看