现在出去面试,别人一问就是你知道多少种设计模式,知道面向对象的设计原则吗?往往有些同志就死在这些节点上,与好工作失之交臂。今天我们看一下装饰模式,这个模式可以应用于什么场景,比如你有个之前的核心业务,我们不敢轻举妄动。但是老大说要修改某个业务逻辑。比如会员管理系统中的消费扣费,因为扣费这个业务牵涉到扣当事人费用,给介绍人提成,记录消费明细,发短信给当时人等一系列核心业务流程。此时老板说我们要加一个消费层次统计,把消费100元以下,100-300,300-500元,500以上的数据记录下来,便于后续统计本店消费层次人群比例。这个时候就需要在扣费的时候根据消费金额把数据统计起来。
消费区间 | 100 | 100-300 | 300-500 | 500-10000 |
次数 | 126 | 369 | 598 | 63 |
这个时候,我们面对这样一个需求,不敢动核心部分的代码。那么就用装饰模式实现一下,装饰下,装饰的功能更丰富。
今天我就以一个魔兽争霸的小例子来阐述以下这个模式。一个英雄接口,有放技能方法。然后有个剑圣,集成了英雄并实现英雄的放技能。
现在我们要在放技能的时候给剑圣吃一个血瓶。假设我不想动剑圣放大招的代码,那么我们可以给他装饰一个吃血瓶的方法。C#可以用汉字作为类名,属性名,所以我就干脆用汉字。
代码如下
public interface 英雄 { void 放技能(); } public class 装饰英雄 : 英雄 { protected 英雄 英雄实例; public 装饰英雄(英雄 英雄实例) { this.英雄实例 = 英雄实例; } public void 放技能() { 英雄实例.放技能(); } } public class 回血装饰英雄 : 装饰英雄 { public 回血装饰英雄(英雄 英雄实例) : base(英雄实例) { } public new void 放技能() { 吃血瓶(); this.英雄实例.放技能(); } private void 吃血瓶() { Console.WriteLine("已回血"); } }
依次是接口,实现,装饰类,具体装饰实现。
这样我们就给剑圣加上了吃血瓶,让它在释放技能的时候不会因为血量太少被杀死。在这里假设一下,英雄不只有剑圣,还有其他的暗影猎手,牛头人,召唤先知,大法师,每个人都有自己的放技能方法,因为大家技能不一样。如果大家都要加一个吃血瓶的方法,我们就可以用这个模式,不至于给每个英雄都加一个吃血瓶,看一下调用。
public class 剑圣 : 英雄 { public void 放技能() { Console.WriteLine("火麟旋风"); } } var 装饰 = new 回血装饰英雄(new 剑圣()); 装饰.放技能();
运行结果如下
已回血 火麟旋风
加入再来个牛头人,如下
public class 牛头人 : 英雄 { public void 放技能() { Console.WriteLine("冲击波"); } }
var 装饰 = new 回血装饰英雄(new 牛头人()); 装饰.放技能();
那么运行结果将会是
已回血 冲击波
OK,今天就到这里,下一节讲讲别的设计模式。
下一篇 设计模式之-适配器模式