设计模式 - D3 - 装饰者模式

设计模式 - D3 - 装饰者模式

装饰者模式

编写程序时,利用继承设计子类的行为是在编译时静态决定的,且所有子类都会继承到相同的行为;相反,利用组合的做法扩展对象的行为,可以在运行时动态地扩展,在使用新代码添加新功能的同时,无须修改现有代码,进而减少产生bug的机会
假设现在有一个超类Beverage,其中的属性代表了各式调料,cost()方法会计算所有调料的价钱;为了提供各式各样的饮料,每个子类都需要继承超类Beverage,并重写cost()方法,扩展超类的功能,计算该饮料的价钱
在这里插入图片描述

开闭原则

但这种设计存在一个问题:出现新调料的时候需要修改超类Beverage,以及某些饮料可能继承了一些不合适的方法
显然,这种设计违反了开闭原则

开闭原则:类应该对扩展开放,对修改关闭

改进:以饮料为主体,在运行时以调料来“装饰”饮料,如:当顾客想要一杯加奶泡(Whip)的摩卡(Mocha时),先创建一个DarkRoast对象,然后创建一个Mocha对象包裹DarkRoast,然后再创建一个Whip对象包裹Mocha,当客户需要付款时,调用最外圈的装饰者(此处为Whip)的cost(),而cost()调用所装饰对象(此处为Mocha)的cost()递归计算价钱即可
在这里插入图片描述

定义

装饰者模式动态地将责任附加到对象上;若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

特点

  • 装饰者和被装饰对象具有相同的超类型
  • 可用一个或多个装饰者包装一个对象
  • 任何需要原始对象(被包装的,如:DarkRoast)的场合,可以使用包装过的对象(如:Whip)代替
  • 装饰者可以在所委托被装饰者的行为之前/之后,加上自己的行为,以达到特定的目的(类似于AOP,达到扩展目的)
  • 对象可以再任何时候被装饰,所以可以在运行时动态地、不限量地使用任何一个装饰者来装饰

实现

在这里插入图片描述

  • ConcreteComponent是将要动态地加上新行为的对象,即被装饰者
  • Decorator与ConcreteComponent实现共同的接口或抽象类,同时它也是装
  • ConcreteDecoratorA和ConcreteDecoratorB有一个实例变量保存某个component的引用(即包装一个组件),同时也可以扩展compoent的状态,也可以添加新方法newBehavior()在被装饰者的旧行为前后调用,做一些额外的计算

所以,对于原来的Beverage设计,我们可以使用装饰者模式改进为
在这里插入图片描述

优缺点

优点

  • 装饰者与组件组合时,就加入了新的行为。该新行为,并不是继承自超类,而是由组合对象得来的,即:可以在任何时候实现新的装饰者增加新的行为。如果依赖继承,每当需要新行为时,还需要修改现有代码。

缺点

  • 有时候会加入大量小类,不容易理解
  • 当代码依赖某种特殊类型时,使用装饰者容器产生错误
  • 使用装饰者模式,不仅需要实例化组件,还需要包装组件,增加代码复杂度
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值