装饰器模式.ppt

上传人:仙人指路1688 文档编号:2670410 上传时间:2023-02-21 格式:PPT 页数:45 大小:5.07MB
返回 下载 相关 举报
装饰器模式.ppt_第1页
第1页 / 共45页
装饰器模式.ppt_第2页
第2页 / 共45页
装饰器模式.ppt_第3页
第3页 / 共45页
装饰器模式.ppt_第4页
第4页 / 共45页
装饰器模式.ppt_第5页
第5页 / 共45页
点击查看更多>>
资源描述

《装饰器模式.ppt》由会员分享,可在线阅读,更多相关《装饰器模式.ppt(45页珍藏版)》请在三一办公上搜索。

1、结构型装饰器模式(Decorator),欢迎来到星巴兹咖啡,星巴兹(Starbuzz)是以扩张速度最快而闻名的咖啡连锁店如果你在街角看到它的店,在对面街上肯定还会看到另一家因为扩张速度实在太快了,他们准备更新订单系统,以合乎他们的饮料供应要求他们原先的类设计是这样的,购买咖啡时,也可以要求在其中加入各种调料,例如:蒸奶(Steamed Milk)、豆浆(Soy)、摩卡(Mocha,也就是巧克力风味)或覆盖奶泡星巴兹会根据所加入的调料收取不同的费用所以订单系统必须考虑到这些调料部分这是他们的第一个尝试,为什么设计这么多类呀?利用实例变量和继承,就可以追踪这些调料先从Beverage基类下手,加上

2、实例变量代表是否加上调料(牛奶、豆浆、摩卡、奶泡),请为下面类的cost()方法书写代码(用伪Java代码即可),public class Beverage public double cost(),public class DarkRoast extends Beverage public DarkRoast()description=“Most Excellent Dark Roast”;public double cost(),public class DarkRoast extends Beverage public DarkRoast()description=“Most Excel

3、lent Dark Roast”;public double cost()return 1.99+super.cost();,潜在的问题,当哪些需求或因素改变时会影响这个设计?调料价钱的改变会使我们更改现有代码一旦出现新的调料,我们就需要加上新的方法,并改变超类中的cost()方法以后可能会开发出新饮料。对这些饮料而言(例如:冰茶),某些调料可能并不适合,但是在这个设计方式中,Tea(茶)子类仍将继承那些不适合的方法,例如:hasWhip()(加奶泡)万一顾客想要双倍摩卡咖啡,怎么办?,尽管继承威力强大,但是体会到它并不总是能够实现最有弹性和最好维护的设计不通过继承又能如何达到复用呢?利用组合

4、(composition)和委托(delegation)可以在运行时具有继承行为的效果利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展,可以利用此技巧把多个新职责,甚至是设计超类时还没有想到的职责加在对象上。而且,可以不用修改原来的代码利用组合维护代码。通过动态地组合对象,可以写新的代码添加新功能,而无须修改现有代码既然没有改变现有代码,那么引进bug或产生意外副作用的机会将大幅度减少,开放-关闭原则,类应该对扩展开放,对修改关闭我们的目标是允许类容易扩展,在不修改现有代码的情况下,就可搭

5、配新的行为如能实现这样的目标,有什么好处呢?这样的设计具有弹性可以应对改变,可以接受新的功能来应对改变的需求想想观察者模式通过加入新的观察者,我们可以在任何时候扩展Subject(主题),而且不需向主题中添加代码,认识装饰者模式,我们已经了解利用继承无法完全解决问题,在星巴兹遇到的问题有:类数量爆炸、设计死板,以及基类加入的新功能并不适用于所有的子类所以,在这里要采用不一样的做法:我们要以饮料为主体,然后在运行时以调料来“装饰”(decorate)饮料,比方说,如果顾客想要摩卡和奶泡深焙咖啡,那么,要做的是:拿一个深焙咖啡(DarkRoast)对象以摩卡(Mocha)对象装饰它以奶泡(Whip

6、)对象装饰它调用cost()方法,并依赖委托(delegate)将调料的价钱加上去但是如何“装饰”一个对象,而“委托”又要如何与此搭配使用呢?给一个暗示:把装饰者对象当成“包装者”。让我们看看这是如何工作的,以DarkRoast对象开始,以装饰者构造饮料订单,顾客想要摩卡(Mocha),所以建立一个Mocha对象,并用它将DarkRoast对象包(wrap)起来,顾客也想要奶泡(Whip),所以需要建立一个Whip装饰者,并用它将Mocha对象包起来。别忘了,DarkRoast继承自Beverage,且有一个cost()方法,用来计算饮料价钱。,现在,该是为顾客算钱的时候了。通过调用最外圈装饰

7、者(Whip)的cost()就可以办得到。Whip的cost()会先委托它装饰的对象(也就是Mocha)计算出价钱,然后再加上奶泡的价钱。,装饰者和被装饰对象有相同的超类型你可以用一个或多个装饰者包装一个对象既然装饰者和被装饰对象有相同的超类型,所以在任何需要原始对象(被包装的)的场合,可以用装饰过的对象代替它装饰者可以在所委托被装饰者的行为之前与/或之后,加上自己的行为,以达到特定的目的对象可以在任何时候被装饰,所以可以在运行时动态地、不限量地用你喜欢的装饰者来装饰对象,这是目前所知道的一切,装饰者模式动态地将责任附加到对象上若要扩展功能,装饰者提供了比继承更有弹性的替代方案,定义装饰者模式

8、,装饰我们的饮料,在继承和组合之间,观念有一些混淆,有一点混淆我原以为在这个模式中不会使用继承,而是要利用组合取代继承看看类图。CondimentDecorator扩展自Beverage类,这用到了继承的确是如此,但这么做的重点在于,装饰者和被装饰者必须是一样的类型,也就是有共同的超类,这是相当关键的地方。在这里,我们利用继承达到“类型匹配”,而不是利用继承获得“行为”为何装饰者需要和被装饰者(亦即被包装的组件)有相同的“接口”,因为装饰者必须能取代被装饰者但是行为又是从哪里来的?当我们将装饰者与组件组合时,就是在加入新的行为。所得到的新行为,并不是继承自超类,而是由组合对象得来的,将装饰者与

9、组件组合时,就是在加入新的行为。所得到的新行为,并不是继承自超类,而是由组合对象得来的继承Beverage抽象类,是为了有正确的类型,而不是继承它的行为。行为来自装饰者和基础组件,或与其他装饰者之间的组合关系因为使用对象组合,可以把所有饮料和调料更有弹性地加以混和与匹配,非常方便。如果依赖继承,那么类的行为只能在编译时静态决定。换句话说,行如果不是来自超类,就是子类覆盖后的版本。反之,利用组合,可以把装饰者混合着用而且是在“运行时”可以在任何时候,实现新的装饰者增加新的行为。如果依赖继承,每当需要新行为时,还得修改现有的代码,代码清单,写下星巴兹的代码,先从Beverage类下手,这不需要改变

10、星巴兹原始的设计。如下所示:,代码清单,让我们也来实现Condiment(调料)抽象类,也就是装饰者类:,现在,已经有了基类,让我们开始开始实现一些饮料先从浓缩咖啡(Espresso)开始我们还需要为具体的饮料设置描述,而且还必须实现cost()方法,写饮料的代码,代码清单,如果回头去看看装饰者模式的类图,将发现我们已经完成了抽象组件(Beverage),有了具体组件(HouseBlend),也有了抽象装饰者(CondimentDecorator)现在,我们就来实现具体装饰者。先从摩卡下手:,写调料代码,代码清单,供应咖啡,我们在星巴兹的朋友决定开始在菜单上加上咖啡的容量大小,供顾客可以选择小

11、杯(tall)、中杯(grande)、大杯(venti)星巴兹认为这是任何咖啡都必须具备的,所以在Beverage类中加上了getSize()与setSize()他们也希望调料根据咖啡容量收费,例如:小中大杯的咖啡加上豆浆,分别加收0.10、0.15、0.20美金如何改变装饰者类应对这样的需求?,习题解答,真实世界的装饰者:Java I/O,装饰java.io类,编写自己的Java I/0装饰者,编写一个装饰者,把输入流内的所有大写字符转成小写举例:当读取“I know the Decorator Pattern therefore I RULE!”,装饰者会将它转成“i know the d

12、ecorator pattern therefore i rule!”,测试你的新Java I/O装饰者,要点,继承属于扩展形式之一,但不见得是达到弹性设计的最佳方式在我们的设计中,应该允许行为可以被扩展,而无须修改现有的代码组合和委托可用于在运行时动态地加上新的行为除了继承,装饰者模式也可以让我们扩展行为装饰者模式意味着一群装饰者类,这些类用来包装具体组件装饰者类反映出被装饰的组件类型(事实上,他们具有相同的类型,都经过接口或继承实现),要点,装饰者可以在被装饰者的行为前面与/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的你可以用无数个装饰者包装一个组件装饰者一般对组件的客户是透明的,除非客户程序依赖于组件的具体类型装饰者会导致设计中出现许多小对象,如果过度使用,会让程序变得很复杂,OO原则,封装变化多用组合,少用继承针对接口编程,不针对实现编程为交互对象之间的松耦合设计而努力对扩展开放,对修改关闭,Any Question?,Thank you,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 建筑/施工/环境 > 项目建议


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号