《Head First Design Patterns》笔记三:装饰者模式(Decorator Pattern)

前言

    什么是装饰呢,通俗来说,人靠衣装,佛靠金装,这里呢,人就是被装饰者,衣服就是装饰品,你穿再多衣服,性质没变,还是个人啦,你还是可以再戴上新戒指,而不必关心这人之前穿了什么衣服.

    引申到软件工程里呢,就是一个已存在的类,可能需要不断的增加新功能,那么我们新建新功能 当做装饰品,装饰现有的类,而不必要去不断修改已有的代码,要知道碰旧代码通常是一件让人头疼的事情.这符合设计模式的一个原则:对扩展开放,而对修改关闭.就是说有新功能我们尽量在外部扩展用新代码,而不是去内部修改旧的代码,把新功能加进去.ok,闲话少说,言归正传,我们这里以一个咖啡店作为例子来讲解这个装饰者模式.

需求

    新业务上门了,现在我们需要为一家咖啡店做买单系统,咖啡店提供的咖啡有espresso(浓缩咖啡) ,houseblend(家常咖啡),配料有 peppermint syrup(薄荷汁),milk(牛奶),soy(豆浆),mocha(摩卡,就是里面加巧克力),whipped milk(奶泡,会浮在上面的那种热牛奶,泡沫状),1种咖啡,加任意1种或多种配料就可以组合成几十上百种咖啡了

初步设计

   我们当然可以去玩排列组合的把戏,把所有能组成的咖啡都去做1个类,那就是个类炸弹,把我们会炸晕的. so我们考虑把配料作为成员,放在咖啡类里面.设计如图

   参考以上uml图表,有加牛奶的话,就设置hasMilk为true.加豆浆的话就设置hasSoy为true,这样就很容易实现需求,但是问题来了,一旦有了新的配料呢, 那么我们就不得的不修改coffee类了,如果用户不只要1份milk,而是要double呢,这些后期维护问题使得我们不断的修改原有的代码,这破坏了类的封装,违反了我们的设计原则,尽量对扩展开放,而不是对修改开放.

进一步设计

    我们考虑装饰者模式,客户可以在运行时动态的增添功能,而不是在编译的时候去增添功能.这样的设计十分灵活.如下图.

再回头考虑咖啡店,把咖啡作为ConcreteComponent,把调料作为DecoratorComponent,咖啡加入任何调料,还是一杯咖啡,继续增添新调料的话,不需要关心前面已经加入了哪种调料,有新的调料加入时,只需要增加一个新的调料的类,其他代码不需要做任何修改.uml作图如下

 

代码

   剩下的就是代码实现了, 这里把代码分为9个类,

   首先是3个类,IBerverage接口,Espresso类,HouseBlend类,如下:

然后是扮演装饰角色的5个类,包括IDecoratorBeverage虚类,Milk类,Mint类,Soy类,Whip类

如下:

最后就是测试运行代码了 Program.cs 如下:

运行结果:

 

Espresso:$10
Espresso Soy Whip:$12.5
HouseBlend Mint Milk Milk:$14.5


总结

     装饰者模式就是可以动态的将组件添加到已有的类中,以实现新功能。我们在实际编程中遇见需求更改,添加新功能的时候经常用到这个模式,这也符合面向对象的一个设计原则:尽量使用组合,而不是继承

 

下一篇:《Head First Design Patterns》笔记四:工厂模式(Factory Pattern)

上一篇:《Head First Design Patterns》笔记二:观察者模式(Observer Pattern)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值