装饰模式

装饰模式:Decorator

1、基本原理

在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?这就是本文要讲的Decorator模式。

装饰模式(别名Wrapper)是在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。它通过创建一个包装对象,也就是装饰来包裹真实对象,提供了比继承更具弹性的代替方案。

装饰模式一般涉及到的角色

抽象构建角色(Component):给出一个抽象的接口,以规范准备接受附加责任的对象。

具体的构建角色(ConcreteComponent):定义一个将要接受附加责任的类。

抽象的装饰角色 (Decorator):持有一个抽象构建(Component)角色的引用,并定义一个与抽象构件一致的接口。

具体的装饰角色(ConcreteDecorator):负责给构建对象“贴上”附加的责任。

 

2、优缺点

 优点

 Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。

 把类中的装饰功能从类中搬移出去,这样可以简化原有的类。有效地把类的核心功能和装饰功能区分开了。 

 通过使用不同的具体装饰类以及这些装饰类的排列组合,可创造出很多不同行为的组合。

 缺点

 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。

 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。

 符合的设计原则:

 多用组合,少用继承。利用继承设计子类的行为是在编译时静态决定的,且所有的子类都会继承到相同的行为。如能够利用组合扩展对象的行为,就可在运行时动态进行扩展。

 类应设计的对扩展开放,对修改关闭。

3、适用情况

1. 需要扩展一个类的功能,或给一个类添加附加职责。

2. 需要动态的给一个对象添加功能,这些功能可以再动态的撤销。

3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变的不现实。

4. 当不能采用生成子类的方法进行扩充时。一种情况是,可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。

4、应用举例

1、送生日蛋糕:

MM们要过生日了,怎么也得表示下吧。最起码先送个蛋糕。蛋糕多种多样了。巧克力,冰淇淋,奶油等等。这都是基本的了,再加点额外的装饰,如蛋糕里放点花、放贺卡、放点干果吃着更香等等。

分析:

方案1:如果采用继承会造成大量的蛋糕子类

方案2、蛋糕作为主体,花,贺卡,果仁等是装饰者,需要时加到蛋糕上。要啥我就加啥。

 

2、极品飞车喷涂鸦:

 “极品飞车”这款游戏中有对汽车进行喷涂鸦的功能,而且这个喷涂鸦是可以覆盖的,并且覆盖的顺序也影响到最后车身的显示效果,比如可以是红色火焰、紫色霞光等

 

3、Java I/O API

java IO中需要完成对不同输入输出源的操作,如果单纯的使用继承这一方式,无疑需要很多的类。比如说,我们操作文件需要一个类,实现文件的字节读取需要一个类,实现文件的字符读取又需要一个类....一次类推每个特定的操作都需要一个特定的类。这无疑会导致大量的IO继承类的出现。显然对于编程是很不利的。

而是用装饰模式则可以很好的解决这一问题,在装饰模式中:节点流(如FileInputStream)直接与输入源交互,之后通过过滤流(FilterInputStream)进行装饰,这样获得的io对象便具有某几个的功能,很好的拓展了IO的功能。

 

 

5、其他

5.1装饰模式和继承的比较

 

装饰模式

继承

用来扩展特定对象的功能

用来扩展一类对象的功能

不需要子类

需要子类

动态地

静态地

运行时分配职责

编译时分派职责

防止由于子类而导致的复杂和混乱

导致很多子类产生,在一些场合,报漏类的层次

更多的灵活性

缺乏灵活性

对于一个给定的对象,同时可能有不同的装饰对象,客户端可以通过它的需要选择合适的装饰对象发送消息

对于所有可能的联合,客户期望

很容易增加任何的扩展

困难扩展

 

5.2、模式的简化:

1. 如果只有一个Concrete Decorator类时,可以将Decorator和Concrete Decorator合并。

 

2、如果只有一个Concrete Component类而没有抽象的Component接口时,可以让Decorator继承Concrete Component。

 

 

总结

Decorator模式采用对象组合而非继承的手法,实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的“灵活性差”和“多子类衍生问题”。同时它很好地符合面向对象设计原则中“优先使用对象组合而非继承”和“开放-封闭”原则。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值