- 浏览: 105550 次
- 性别:
- 来自: 深圳
-
文章分类
最新评论
装饰模式,The Decorator Pattern attaches additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. 动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
让我们来理解这句话。
我们系统中设计了“门”这个类。 <!--[if !vml]--><!--[endif]-->
现在,在系统的一个地方需要一个能够报警的Door,你来怎么做呢?你或许写一个Door的子类AlarmDoor,在里面添加一个子类独有的方法alarm()。嗯,那在使用警报门的地方你必须让客户(使用者)知道使用的是警报门,不然无法使用这个独有的方法。而且,这个还违反了Liskov替换原则。
也许你要说,那就把这个方法添加到Door里面,这样不就统一了?但是这样所有的门都必须有警报,至少是个“哑巴”警报。而当你的系统仅仅在一两个地方使用了警报门,这明显是不合理的——虽然可以使用缺省适配器来弥补一下。
这时候,你可以考虑采用装饰模式来给门动态的添加些额外的功能。
下面我们来看看装饰模式的组成,不要急着去解决上面的问题,到了下面自然就明白了!
Component
原有类的接口
ConcreteComponent
功能实现类。Component的具体实现类
Decorator
装 饰抽象类。与ConcreteComponent一样都继承了Component接口,但实现的方式与ConcreteComponent有区别。 ConcreteComponent通过单纯继承的方式来实现;而Decorator则通过对Component对象的封装与动作委让方式来实现。
下面是一个典型的Decorator的代码为:
清单1
public class Decorator implement Component {
Component component;
public Decorator(Component component) {
this.component = component;
}
public void doSomething() {
...
this.component.doSomething();
...
}
}
ConcreteDecoratorA 与 ConcreteDecoratorB
具体的装饰类。Decorator的具体实现类
下面是类图

下面看一个更具体的例子:
Central Perk的名字因为《老友记》而享誉全球,他们的分店几乎开遍世界各地。他们发展的实在是太快了,所以他们此时正在急于实现一套由计算机管理的自动化记账系统。对于一家咖啡店来说,都有那些变化点呢?调味品的品种和价格会变吗?咖啡的品种和价格会变吗?咖啡和调味品的组合方式会变吗?YES! 对于一家咖啡店来说,这些方面肯定会经常发生改变的!那么,当这些改变发生的时候,我们的记账系统要如何应对呢? 如果调味品发生改变,那么我们只能从代码的层次重新调整Beverage基类,这太糟糕了;如果咖啡发生改变,我们可以增加或删除一个子类即可,这个似乎还可以忍受;那么咖啡和调味品的组合方式发生改变呢?如果顾客点了一杯纯黑咖啡外加两份砂糖和一份巧克力,或者顾客点了一杯脱咖啡因咖啡(Decaf)外加三份炼乳和一份砂糖呢?
那么回到装饰者模式,跟前面介绍过的模式一样,装饰者同样是一个很简单的模式,特别是画出类图和顺序图之后,一切都很清楚明了。这里只有一个地方需要特殊强调一下:Decorator是装饰者模式里非常特殊的一个类,它既继承于Component【IS A关系】,又维护一个指向Component实例的引用【HAS A关系】,换个角度来说,Decorator跟Component之间,既有动态组合关系又有静态继承关系,WHY? 这里为什么要这么来设计?上面我们说过,组合的好处是可以在运行时给对象增加职责,Decorator【HAS A】Component的目的是让ConcreteDecorator可以在运行时动态给ConcreteComponent增加职责,这一点相对来说还比较好理解;那么Decorator继承于Component的目的是什么?在这里,继承的目的只有一个,那就是可以统一装饰者和被装饰者的接口,换个角度来说,不管是ConcretComponent还是ConcreteDecorator,它们都是 Component,用户代码可以把它们统一看作Component来处理,这样带来的更深一层的好处就是,装饰者对象对被装饰者对象的功能职责扩展对用户代码来说是完全透明的,因为用户代码引用的都是Component,所以就不会因为被装饰者对象在被装饰后,引用它的用户代码发生错误,实际上不会有任何影响,因为装饰前后,用户代码引用的都是Component类型的对象,这真是太完美了!装饰者模式通过继承实现统一了装饰者和被装饰者的接口,通过组合获得了在运行时动态扩展被装饰者对象的能力。
我们再举个生活中的例子,俗话说“人在衣着马在鞍”,把这就话用装饰者模式的语境翻译一下,“人通过漂亮的衣服装饰后,男人变帅了,女人变漂亮了;”。对应上面的类图,这里人对应于ConcreteComponent,而漂亮衣服则对应于ConcreteDecorator;换个角度来说,人和漂亮衣服组合在一起【HAS A】,有了帅哥或美女,但是他们还是人【IS A】,还要做人该做的事情,但是可能会对异性更有吸引力了(扩展功能)!
从装饰者模式的角度来考虑问题,咖啡和调味品的关系应该 是:咖啡是被装饰对象而调味品是装饰者,咖啡和调味品可以任意组合,但是不管怎么组合,咖啡还是咖啡!原来这么简单啊!
具体看下面的类图:

如图所示,Beverage还是所有饮料的基类,它对应于装饰者模式类图里的Component,是所有被装饰对象的基类;HouseBlend, DarkRoast, Espresso, Decaf是具体的饮料(咖啡)种类,对应于前面的ConcreteComponent,即是具体的被装饰对象;CondimentDecorator对应于前面的Decorator,是装饰者的抽象类;而Milk,Mocha,Soy,Whip则都是具体的调味品,对于前面的ConcreteDecorator,也就是具体的装饰者。下面我们通过具体的代码再进一步理解一下基于装饰者模式的记账系统的实现。
Beverage还是所有饮料的基类,它对应于装饰者模式类图里的Component,是所有被装饰对象的基类
|
HouseBlend, DarkRoast, Espresso, Decaf是具体的饮料(咖啡)种类,对应于前面的ConcreteComponent,即是具体的被装饰对象;
|
|
CondimentDecorator对应于前面的Decorator,是装饰者的抽象类
|
而Milk,Mocha,Soy,Whip则都是具体的调味品,对于前面的ConcreteDecorator,也就是具体的装饰者
|
|
好了。下面给出测试代码:
|
输出:
|
至此应该讲清楚了什么是装饰模式了吧。
说明:
本文是对以下三个连接的博文进行整理得到的,相信看一下三篇博文会有更大的收获。
参考:
http://blog.csdn.net/ai92/archive/2005/03/01/307046.aspx
http://www.cnblogs.com/justinw/archive/2007/06/11/779356.html
http://www.lifevv.com/sysdesign/doc/20071116210104656.html
发表评论
-
设计模式之 State - 状态模式
2010-12-18 16:49 1156State模式也叫状态模式,是由GoF提出的23种软件设计模式 ... -
设计模式之 Strategy - 策略模式
2010-12-18 16:46 1425Strategy模式也叫策略模 ... -
设计模式之 Visitor - 访问者模式
2010-12-18 16:45 1499Visitor模式也叫访问者 ... -
设计模式之 Template Method - 模板方法模式
2010-12-18 16:41 1612Template Method模式也叫模板方法模式,是由G ... -
设计模式之 Observer - 观察者模式
2010-12-18 16:33 1462Observer模式也叫观察者 ... -
设计模式之 Memento - 备忘录模式
2010-12-18 16:31 1125Memento模式也叫备忘录 ... -
设计模式之 Mediator - 中介者模式
2010-12-18 16:29 1173Mediator模式也叫中介者模式,是由GoF提出的23种软件 ... -
设计模式之 Iterator - 迭代模式
2010-12-18 16:27 1226Iterator模式也叫迭代模式,是由GoF提出的23种设 ... -
设计模式之 Interpreter - 解释器模式
2010-12-18 16:23 1055Interpreter模式也叫解释器模式,是由GoF提出的 ... -
设计模式之 Command - 命令模式
2010-12-18 16:20 971Command(CoR)模式也叫命 ... -
设计模式之 Chain of Responsibility - 职责链模式
2010-12-18 16:18 1260Chain of Responsibility(CoR)模 ... -
设计模式之 Proxy - 代理模式
2010-12-16 23:45 1126Proxy模式也叫代理模式,是由GoF提出的23种软件设计 ... -
设计模式之 Flyweight - 享元模式
2010-12-16 23:42 1121Flyweight模式也叫享元模式,是由GoF提出的23种 ... -
设计模式之 Facade - 外观模式
2010-12-16 23:41 1078Facade模式也叫外观模式 ... -
设计模式之 Singleton - 单态模式
2010-11-26 11:58 902Singleton模式也叫单态模式,是由GoF提出的2 ... -
设计模式之 Composite - 组合模式
2010-11-25 23:35 1522Composite模式也叫组合 ... -
设计模式之 Bridge - 桥接模式
2010-11-25 23:08 1062Bridge模式也叫桥接模式,是由GoF提出的23种软件设计模 ... -
设计模式之 Adapter - 适配器模式
2010-11-25 22:58 966Adapter模式也叫适配器模式,是由GoF提出的23种设 ... -
设计模式之Prototype - 原型模式
2010-11-25 22:14 1177Prototype模式也叫原型模式,是由GoF提出的23种设计 ... -
设计模式之 Builder - 建造者模式
2010-11-18 23:51 1127Builder模式也叫建造者模式或者生成器模式,是由GoF ...
相关推荐
【低空经济】低空人工智能调度中心建设方案
少儿编程scratch项目源代码文件案例素材-诅咒大厦.zip
scratch少儿编程逻辑思维游戏源码-纸片马里奥 激流勇进.zip
scratch少儿编程逻辑思维游戏源码-一路跳跃.zip
内容概要:本文详细介绍了五个用于空气耦合超声仿真的COMSOL模型,涵盖二维和三维场景,适用于铝板和钢板的多种缺陷检测。每个模型都包含了具体的参数设置、边界条件选择以及优化技巧。例如,Lamb波检测模型展示了如何利用A0模态检测铝板内的气泡,而三维模型则强调了内存管理和入射角参数化扫描的重要性。表面波检测模型提供了裂纹识别的相关性分析方法,变厚度模型则展示了如何通过几何参数化来模拟复杂的工件形态。文中还分享了许多实用的操作技巧,如内存优化、信号处理和自动化检测逻辑。 适用人群:从事无损检测研究的技术人员、COMSOL软件使用者、超声检测领域的研究人员。 使用场景及目标:①帮助用户理解和掌握空气耦合超声仿真的具体实现方法;②提供实际工程应用中的缺陷检测解决方案;③指导用户进行高效的仿真建模和结果分析。 其他说明:文中提供的模型不仅涵盖了常见的缺陷检测场景,还包括了一些高级技巧,如参数化扫描、自动化检测逻辑等,能够显著提高工作效率。同时,文中还给出了硬件配置建议和一些常见的注意事项,确保用户可以顺利运行这些模型。
实训商业源码-【脐橙】租赁 2.80.0+租赁商家-毕业设计.zip
scratch少儿编程逻辑思维游戏源码-幽灵冲刺.zip
scratch少儿编程逻辑思维游戏源码-粘粘世界物理.zip
机器人开发教程&案例&相关项目资源,奖励仅
实训商业源码-酒吧微上墙4.1.0-毕业设计.zip
实训商业源码-会员计次卡V1.1.1-毕业设计.zip
实训商业源码-二手跳蚤市场V5.4.10带微信支付+上架通知+广告插件-毕业设计.zip
实训商业源码-健康保健类企业网站源码-毕业设计.zip
Linux环境安装mysql的RPM包以及安装步骤:客户端和服务端的安装
实训商业源码-房产中介小程序8.0.51+前端-毕业设计.zip
scratch少儿编程逻辑思维游戏源码-钟声.zip
实训商业源码-【最新版】Xyplayer X3.96 官方正式版-毕业设计.zip
scratch少儿编程逻辑思维游戏源码-追逐游戏.zip
内容概要:本文详细介绍了基于Android Studio开发的日历备忘录记事本项目,涵盖日历查看、添加备忘录、闹钟提醒和删除备忘录等功能。项目使用SQLite数据库进行数据管理和持久化,利用AlarmManager实现闹钟提醒功能。文章深入讲解了各个功能模块的实现细节,如日历视图的使用、数据库操作类的设计、闹钟设置的逻辑以及界面交互的优化。此外,还探讨了一些常见的开发技巧和注意事项,如时间戳的存储、手势识别的应用等。 适用人群:适用于初学者和有一定经验的Android开发者,尤其是希望深入了解SQLite数据库操作和AlarmManager使用的开发者。 使用场景及目标:① 学习如何使用Android Studio构建完整的应用程序;② 掌握SQLite数据库的基本操作,包括建表、增删查改;③ 理解AlarmManager的工作机制及其在实际项目中的应用;④ 提升用户体验,如优化界面交互和提高代码质量。 其他说明:文中提供的源码和详细的代码注释有助于读者更好地理解和实践。同时,项目中预留了一些扩展任务,鼓励读者进一步探索和提升技能。
X52K数控铣床改造纵向进给机构CAD装配图.rar