模式人生-从生活中的点点滴滴认识设计模式1-装饰器模式(Decorator Pattern)
从生活中的点点滴滴认识设计模式系列(一)
装饰器模式(Decorator Pattern)
“老樊,老樊……”,一听这熟悉的大嗓门就知道是公司里的小刘在叫我。
小刘可是个美女,刚进公司不久,出落得亭亭玉立,就是人凶了点、嗓门大了点,不过她一进公司就被公司里的那一群狼盯上了,个个都跟她套近乎,一个月便成了公司里的红人。
也许是本工程师比较年轻比较帅吧,小刘就喜欢跟我搭腔,不知道今天她又找我干嘛。
只见她大步流星的来到我面前,用她那迷死人的眼睛盯着我说:“老樊,有件事情要你帮帮忙!”
“什么事情啊?”
“你先说你答应不答应嘛!”
“呃……什么事情都不知道就答应,要是到时你让我下嫁于你我不吃亏啦!”
“你想得美哦!那我就告诉你吧,本小姐最近在学习设计模式,希望你能给我点指导!”
“哦,原来就这点事啊,好吧,我答应你,不过学习设计模式可不是一天两天的事情!”
“嗯,我一定会努力学的!”
“那好,从今天开始你就叫我师傅吧!”
“嗯,师傅,嘻嘻!”
这回我心里可美了,收了个美女徒弟,以后经常有美相伴,何乐而不为!
“明天星期六公司组织烧烤,我给你上樊式设计模式第一课:装饰器模式。”
“也,好也,那明天见咯!Byebye!”说完就屁颠屁颠的跑了。
第二天
公司人太多,我和小刘没有分到一辆车。
一路颠簸,也不知道过了多久,迷迷糊糊的我被人拉了起来。
“老樊,到啦,快起来啦!”
唉,一定是昨天晚上打游戏打到太晚了,搞得今天这么困。
“老樊,你看我的鸡翅烤得多漂亮,你再看看你的,就一黑炭,不过和你还真象,都是这么黑!”小刘拿着她烤的鸡翅在我面前炫耀,再看看我手上的,都成炭了,但也只能硬着头皮吃了。
“小刘,你就别损我了,我天生就没有烹饪天份。不过到了上课时间了,我要跟你讲的装饰器模式就跟今天的烧烤有关。”
听完我说的,小刘马上严肃下来,睁着大眼睛盯着我,生怕错过了一个细节。
装老成,咳嗽两声后。
“装饰器,就是往现有的对象上添加新的东西,就象我们烧烤一样,如果你要烤一个鸡翅,你得在烤的过程中不断的往鸡翅上刷油,等到鸡翅快熟了,得撒上盐、刷上酱,这样我们才能烤出一个美味的鸡翅!”
“装饰器模式的好处就是:1. 原始对象可以不知道将要添加的东西是什么,如鸡翅你可以根据口味选择是刷辣椒酱还是番茄酱;2. 添加的东西之间是彼此独立的;3. 添加的东西不一定要按顺序,可以随意混合,如你可以先撒盐、再刷油,不一定要先刷油再撒盐!”
小刘一边听一边点头:“老樊,虽然我还不知道怎么去写装饰器的代码,但是听你这么一说,我已经知道什么是装饰器模式了。就拿我当成一个对象,我衣柜里的衣服裤子便都是用来装饰我的东西,而这些衣服裤子我可以随意搭配,他们之间也是相互独立的是么?”
“嗯,孺子可教也!晚上回到家我会写一段烤鸡翅相关的装饰器代码给你,到时候你好好看看吧!”
晚上回到家我就把装饰器模式UML图以及烤鸡翅的代码发给了小刘。
UML图:
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); } } }
程序运行结果:
哈哈,一个香喷喷的鸡翅就出来啦!
如果想烤其它的东西,则可以再新建一个实现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); } } }
我只放油和辣椒酱,不想吃盐,结果如下:
再来对装饰器模式进行一下总结:
装饰器模式就是往已有的原始对象上添加新的内容,装饰器模式属于结构型模式。
装饰器模式的关键特性是它不需要靠继承来扩展行为。
装饰器的好处:
1. 原始对象和装饰类之间分离,原始对象可以不知道装饰类。
2. 装饰类之间是彼此独立的,不会互相影响。
3. 装饰类在对原始对象进行装饰时可随意组合。
通过邮件将资料发给小刘已经是深夜了,不知道小刘是否已休息,俺也该休息去啦,希望在梦中能见到俺的梦中情人!!!
文章源代码:
从生活中的点点滴滴认识设计模式系列文章:
1. 从生活中的点点滴滴认识设计模式1-装饰器模式(Decorator Pattern)
2. 从生活中的点点滴滴认识设计模式2-策略模式(Strategy Patten)
3. 从生活中的点点滴滴认识设计模式3-单件模式(Singlegon Patten)