模式人生-从生活中的点点滴滴认识设计模式1-装饰器模式(Decorator Pattern)

 

从生活中的点点滴滴认识设计模式系列(一)

装饰器模式(Decorator Pattern)

 

“老樊,老樊……”,一听这熟悉的大嗓门就知道是公司里的小刘在叫我。

小刘可是个美女,刚进公司不久,出落得亭亭玉立,就是人凶了点、嗓门大了点,不过她一进公司就被公司里的那一群狼盯上了,个个都跟她套近乎,一个月便成了公司里的红人。

也许是本工程师比较年轻比较帅吧,小刘就喜欢跟我搭腔,不知道今天她又找我干嘛。

只见她大步流星的来到我面前,用她那迷死人的眼睛盯着我说:“老樊,有件事情要你帮帮忙!”

“什么事情啊?”

“你先说你答应不答应嘛!”

“呃……什么事情都不知道就答应,要是到时你让我下嫁于你我不吃亏啦!”

“你想得美哦!那我就告诉你吧,本小姐最近在学习设计模式,希望你能给我点指导!”

“哦,原来就这点事啊,好吧,我答应你,不过学习设计模式可不是一天两天的事情!”

“嗯,我一定会努力学的!”

“那好,从今天开始你就叫我师傅吧!”

“嗯,师傅,嘻嘻!”

这回我心里可美了,收了个美女徒弟,以后经常有美相伴,何乐而不为!

“明天星期六公司组织烧烤,我给你上樊式设计模式第一课:装饰器模式。”

“也,好也,那明天见咯!Byebye!”说完就屁颠屁颠的跑了。

 

第二天

公司人太多,我和小刘没有分到一辆车。

一路颠簸,也不知道过了多久,迷迷糊糊的我被人拉了起来。

“老樊,到啦,快起来啦!”

唉,一定是昨天晚上打游戏打到太晚了,搞得今天这么困。

 

“老樊,你看我的鸡翅烤得多漂亮,你再看看你的,就一黑炭,不过和你还真象,都是这么黑!”小刘拿着她烤的鸡翅在我面前炫耀,再看看我手上的,都成炭了,但也只能硬着头皮吃了。

“小刘,你就别损我了,我天生就没有烹饪天份。不过到了上课时间了,我要跟你讲的装饰器模式就跟今天的烧烤有关。”

听完我说的,小刘马上严肃下来,睁着大眼睛盯着我,生怕错过了一个细节。

装老成,咳嗽两声后。

“装饰器,就是往现有的对象上添加新的东西,就象我们烧烤一样,如果你要烤一个鸡翅,你得在烤的过程中不断的往鸡翅上刷油,等到鸡翅快熟了,得撒上盐、刷上酱,这样我们才能烤出一个美味的鸡翅!”

“装饰器模式的好处就是:1. 原始对象可以不知道将要添加的东西是什么,如鸡翅你可以根据口味选择是刷辣椒酱还是番茄酱;2. 添加的东西之间是彼此独立的;3. 添加的东西不一定要按顺序,可以随意混合,如你可以先撒盐、再刷油,不一定要先刷油再撒盐!”

小刘一边听一边点头:“老樊,虽然我还不知道怎么去写装饰器的代码,但是听你这么一说,我已经知道什么是装饰器模式了。就拿我当成一个对象,我衣柜里的衣服裤子便都是用来装饰我的东西,而这些衣服裤子我可以随意搭配,他们之间也是相互独立的是么?”

“嗯,孺子可教也!晚上回到家我会写一段烤鸡翅相关的装饰器代码给你,到时候你好好看看吧!”

晚上回到家我就把装饰器模式UML图以及烤鸡翅的代码发给了小刘。

 

UML图:

image

 

IComponent:接口,Component将实现该接口。

Component:原始类,实现IComponent接口,可以有多个。在烤鸡翅例子里为鸡翅。

DecoratorA:实现IComponent接口并添加状态和行为的类。在烤鸡翅例子里为盐、油之类的配料。

DecoratorB:和DecoratorA类相同,但在类里扩展了addedState属性和AddedBehavior操作。

 

装饰器模式代码(烤鸡翅实例):

IComponent.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 接口类
    /// </summary>
    public interface IComponent
    {
        string Operation();
    }
}

 

ChickenWing.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 鸡翅类,实现IComponent接口
    /// </summary>
    public class ChickenWing : IComponent
    {
        public string Operation()
        {
            return "烤鸡翅";
        }
    }
}

 

OilDecorator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 油装饰器
    /// </summary>
    public class OilDecorator : IComponent
    {
        IComponent myComponent;

        public OilDecorator(IComponent component)
        {
            myComponent = component;
        }

        public string Operation()
        {
            string str = myComponent.Operation();
            return str + "  刷上油";
        }
    }
}

 

SaltDecorator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 盐装饰器
    /// </summary>
    public class SaltDecorator : IComponent
    {
        IComponent myComponent;

        public SaltDecorator(IComponent component)
        {
            myComponent = component;
        }

        public string Operation()
        {
            string str = myComponent.Operation();
            return str + "  洒上盐";
        }
    }
}

 

ChiliSauceDecorator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 辣椒酱装饰器
    /// </summary>
    public class ChiliSauceDecorator : IComponent
    {
        IComponent myComponent;

        public ChiliSauceDecorator(IComponent component)
        {
            myComponent = component;
        }

        public string Operation()
        {
            string str = myComponent.Operation();
            return str + "  刷上辣椒酱";
        }
    }
}

 

RedeyeDecorator.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 番茄酱装饰器
    /// </summary>
    public class RedeyeDecorator : IComponent
    {
        IComponent myComponent;

        public RedeyeDecorator(IComponent component)
        {
            myComponent = component;
        }

        public string Operation()
        {
            string str = myComponent.Operation();
            return str + "  刷上番茄酱";
        }
    }
}

 

 Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            string display = "";

            IComponent component = new ChickenWing();

            OilDecorator oilDecorator = new OilDecorator(component);
            
            SaltDecorator saltDecorator = new SaltDecorator(oilDecorator);
            saltDecorator.Operation();

            RedeyeDecorator redeyDecorator = new RedeyeDecorator(saltDecorator);
            display = redeyDecorator.Operation();
            Console.WriteLine(display);
        }
    }
}

 

 

程序运行结果:

image

哈哈,一个香喷喷的鸡翅就出来啦!

 

如果想烤其它的东西,则可以再新建一个实现IComponent的原始对象类,如我想烤牛排:

Steak.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    /// <summary>
    /// 牛排类,实现IComponent接口
    /// </summary>
    public class Steak : IComponent
    {
        public string Operation()
        {
            return "烤牛排";
        }
    }
}

 

更改Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DecoratorPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            string display = "";

            IComponent component = new Steak();

            OilDecorator oilDecorator = new OilDecorator(component);
            
            ChiliSauceDecorator chiliSauceDecorator = new ChiliSauceDecorator(oilDecorator);
            display = chiliSauceDecorator.Operation();
            Console.WriteLine(display);
        }
    }
}

 

我只放油和辣椒酱,不想吃盐,结果如下:

image

 

再来对装饰器模式进行一下总结:

装饰器模式就是往已有的原始对象上添加新的内容,装饰器模式属于结构型模式。

装饰器模式的关键特性是它不需要靠继承来扩展行为。

 

装饰器的好处:

1. 原始对象和装饰类之间分离,原始对象可以不知道装饰类。

2. 装饰类之间是彼此独立的,不会互相影响。

3. 装饰类在对原始对象进行装饰时可随意组合。

 

通过邮件将资料发给小刘已经是深夜了,不知道小刘是否已休息,俺也该休息去啦,希望在梦中能见到俺的梦中情人!!!

文章源代码:

下载



从生活中的点点滴滴认识设计模式系列文章:

1. 从生活中的点点滴滴认识设计模式1-装饰器模式(Decorator Pattern)
2. 从生活中的点点滴滴认识设计模式2-策略模式(Strategy Patten)
3. 从生活中的点点滴滴认识设计模式3-单件模式(Singlegon Patten)

posted @ 2009-07-18 22:56  Terence  阅读(2223)  评论(23编辑  收藏  举报