装饰器模式

合集下载

设计模式:常用设计模式及其应用

设计模式:常用设计模式及其应用

设计模式:常用设计模式及其应用设计模式是在软件设计中常见问题的解决方案的一种反复使用的经验总结。

它们是已经被证明有效的经典解决方案,可以帮助我们在开发过程中避免重复设计。

本文将介绍一些常用的设计模式及其应用。

1.单例模式单例模式是一个创建型的设计模式,它会确保一个类只有一个实例。

这在需要共享资源或控制唯一资源访问的场景下非常实用,例如线程池、日志记录器等。

2.工厂模式工厂模式是一种用于创建对象的创建型设计模式。

它定义了一个接口来创建对象,但将创建实例的过程延迟到子类中。

这样可以避免在代码中直接使用new操作符,增加了代码的灵活性和可维护性。

3.观察者模式观察者模式是一种行为型的设计模式,它定义了一对多的依赖关系。

当一个对象的状态发生变化时,它会自动通知它的依赖对象。

观察者模式常用于事件处理、GUI编程等场景。

4.装饰器模式装饰器模式是一种结构型的设计模式,它允许你通过将对象包装在一个装饰器对象中来动态地添加新的功能。

装饰器模式可以避免使用子类化的复杂性,提供了比继承更加灵活的方式来扩展功能。

5.策略模式策略模式是一种行为型的设计模式,它定义了一系列算法,并将每个算法封装在可以相互替换的策略对象中。

这使得算法可以独立于客户端的使用,提高了代码的灵活性。

6.适配器模式适配器模式是一种结构型的设计模式,它允许不兼容的接口之间进行适配。

适配器模式可以通过创建一个适配器类来实现两个不兼容接口之间的交互。

7. MVC模式MVC(Model-View-Controller)是一种架构模式,它将应用程序分为三个主要部分:模型、视图和控制器。

模型表示应用程序的数据和逻辑,视图负责显示数据,控制器接收用户输入并对模型和视图进行协调。

8.组合模式组合模式是一种结构型的设计模式,它将对象组合成树状结构以表示“整体/部分”层次结构。

组合模式使得用户对单个对象和组合对象的使用具有一致性,可以用来处理树形结构的问题。

9.迭代器模式迭代器模式是一种行为型的设计模式,它提供一种访问容器中各个元素的方法,而不需要暴露容器的内部结构。

面试常见设计模式

面试常见设计模式

面试常见设计模式设计模式是软件开发中常用的一种设计思想,它提供了一种解决问题的方法和模板,帮助开发人员在面对各种复杂问题时能够快速有效地进行设计和开发。

在面试时,设计模式也是面试官经常会问到的一个重要话题。

本文将介绍一些常见的设计模式,并分析其应用场景和优缺点。

1.单例模式单例模式是一种常见的创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。

在多线程环境下,单例模式可以保证线程安全。

单例模式常用于需要共享资源或控制资源访问的场景,比如数据库连接池、线程池等。

2.工厂模式工厂模式是一种创建型设计模式,它定义了一个创建对象的接口,但具体的对象创建由子类决定。

工厂模式可以隐藏对象的创建细节,减少依赖,并且提供了一种可扩展的方式来创建对象。

工厂模式常用于创建复杂对象或对象组合的场景。

3.观察者模式观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生变化时,其依赖的对象将自动收到通知并进行相应的处理。

观察者模式可以实现松耦合,增加对象之间的协作和交互。

观察者模式常用于事件驱动、消息通知等场景。

4.策略模式策略模式是一种行为型设计模式,它将一组算法封装成一系列可互换的策略,使得算法的变化独立于使用算法的客户端。

策略模式可以提高代码的可维护性和可扩展性,减少代码的重复和耦合。

策略模式常用于需要根据不同情况选择不同算法的场景。

5.装饰器模式装饰器模式是一种结构型设计模式,它动态地给一个对象添加一些额外的功能,同时又不改变其原有的结构。

装饰器模式可以在不需要子类化的情况下扩展对象的功能,符合开闭原则。

装饰器模式常用于动态地给对象添加新的行为或功能。

6.适配器模式适配器模式是一种结构型设计模式,它将一个类的接口转换成客户端所期望的另一个接口,使得原本不兼容的接口可以一起工作。

适配器模式可以提高代码的复用性和灵活性,减少代码的改动。

适配器模式常用于不同系统之间的接口转换或旧系统的升级迁移。

装饰器模式详解及代码实现

装饰器模式详解及代码实现

装饰器模式详解及代码实现1. 什么是装饰器模式?装饰器模式是一种结构型设计模式,它允许你在运行时动态地添加行为或修改类功能,而不需要修改原始类的代码。

使用装饰器模式,你可以将对象功能分成单独的部分,然后组合这些部分以创建更加复杂的行为。

装饰器模式是面向对象编程中的一种非常重要的设计模式,也是 Python 语言中广泛使用的一项技术。

2. 装饰器模式的应用场景有哪些?装饰器模式的应用场景很多,下面主要介绍几种典型的情况。

2.1. 在不修改一个对象的前提下,在运行时给对象添加功能。

这个功能可以是动态的,可以在运行时轻松地添加和移除。

例如,你可以动态地向一个已经实例化的对象中添加新的方法和属性。

2.2. 在保持对象的接口和行为不变的前提下,为对象添加功能和行为。

例如,你可以使用装饰器模式为一个基础组件添加缓存、日志记录等功能,而不需要修改组件的代码。

2.3. 作为一种高阶编程技术,利用装饰器模式可以实现函数的函数式编程,使得代码更加简洁、可读性更高。

例如,可以使用装饰器来简洁地实现函数的计时、缓存等功能。

3. 装饰器模式的实现在 Python 中,装饰器主要是通过函数和类来实现的。

下面分别介绍这两种实现方式。

3.1. 使用函数来实现装饰器使用函数来实现装饰器是 Python 中最为常用的实现方式。

下面是一个例子:```pythondef my_decorator(func):def wrapper():print("Before the function is called.")func()print("After the function is called.")return wrapperdef say_hello():print("Hello World!")say_hello = my_decorator(say_hello)# 调用被装饰的函数say_hello()```在这个例子中,首先定义了一个装饰器函数 `my_decorator`,它接受一个函数作为参数。

软件开发中的设计模式及其应用

软件开发中的设计模式及其应用

软件开发中的设计模式及其应用设计模式是由四人带领的软件开发者团队在1994年《设计模式:可复用面向对象软件的基础》一书中提出的。

设计模式是一种被证明有效的解决方案,用于解决面向对象软件设计中的常见问题。

这些模式已被广泛应用于软件开发领域,并被证明可提高软件开发的效率和可重用性。

本文将介绍其中的几种常见设计模式及其应用,以供软件开发者参考。

1.工厂模式工厂模式是一种创建型模式,它提供了一个通用的接口,用于创建对象。

通过使用工厂模式,我们可以隐藏创建对象的实现细节,使得客户端代码无需知道要实例化哪个类。

应用:在开发过程中,我们通常会遇到许多场景需要创建多个对象,而这些对象的创建逻辑可能比较复杂。

在这种情况下,我们可以使用工厂模式来将复杂的对象创建流程进行封装,以简化客户端的代码。

2.单例模式单例模式是一种创建型模式,它确保一个类只有一个实例,并提供全局访问点来访问该实例。

单例模式可以有效地控制全局资源的使用,避免重复创建对象。

应用:单例模式通常适用于多个客户端需要共享相同的资源的情况,例如配置文件、数据库连接对象等全局性的资源。

通过使用单例模式,我们可以避免频繁创建对象,提高资源利用率。

3.装饰器模式装饰器模式是一种结构型模式,它可以在不修改原始对象的情况下,动态地为对象添加新的功能。

装饰器模式通过包装一个对象来扩展其功能,可以灵活地在运行时添加和删除功能。

应用:装饰器模式通常适用于需要动态地扩展对象功能的场景。

例如,我们可以使用装饰器模式为原本只有基本功能的类添加其他功能,例如添加日志记录、性能统计、缓存等。

4.观察者模式观察者模式是一种行为型模式,它定义了一种对象间的一对多依赖关系,使得当其中一个对象发生改变时,所有依赖它的对象都会收到通知,并自动更新。

观察者模式使得对象之间的关系更加松散,增强了对象的可重用性和可扩展性。

应用:在开发过程中,我们经常遇到需要通知其他对象状态变化的场景。

例如,当一份数据更新时,我们需要将此更新通知给其他相关的对象。

软件开发中的设计模式有哪些

软件开发中的设计模式有哪些

软件开发中的设计模式有哪些在软件开发的领域中,设计模式就像是一套经过实践检验的解决方案,帮助开发者更高效、更优雅地解决常见的问题。

它们是软件开发中的宝贵经验总结,为构建可维护、可扩展和灵活的软件系统提供了有力的支持。

接下来,让我们一起探索一下软件开发中常见的设计模式。

一、创建型设计模式1、单例模式(Singleton Pattern)单例模式确保一个类只有一个实例存在,并提供一个全局访问点来获取该实例。

这在某些情况下非常有用,比如一个系统中只需要一个数据库连接池或者一个日志记录器。

想象一下,如果多个线程同时创建多个数据库连接池实例,不仅会浪费资源,还可能导致混乱。

通过单例模式,我们可以保证只有一个实例存在,有效地管理资源。

2、工厂模式(Factory Pattern)当我们需要创建对象,但又不想让客户端直接与具体的类进行交互时,工厂模式就派上用场了。

它定义了一个用于创建对象的接口,让子类决定实例化哪一个类。

比如,在一个汽车生产厂中,有不同类型的汽车(轿车、SUV 等),我们可以通过一个工厂类根据需求来创建相应类型的汽车对象,而客户端只需要向工厂请求即可,无需关心具体的创建细节。

3、抽象工厂模式(Abstract Factory Pattern)抽象工厂模式提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

例如,一个家具厂可能生产多种风格的家具(现代风格、古典风格),每种风格都有配套的椅子、桌子和沙发。

通过抽象工厂模式,我们可以根据用户选择的风格创建一整套家具,保证了风格的一致性和协调性。

4、建造者模式(Builder Pattern)建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

比如构建一个电脑配置,我们可以有不同的 CPU、内存、硬盘等组件选择,通过建造者模式,可以清晰地定义构建的步骤和顺序,同时能够灵活地组合不同的组件来创建出各种不同配置的电脑。

中间件体系结构和设计模式

中间件体系结构和设计模式

中间件体系结构和设计模式在中间件体系结构中,中间件是一个处于应用程序和操作系统之间的软件层。

它提供了一系列的服务和功能,如消息传递、事务处理、分布式计算、安全性等。

通过将复杂的系统功能和业务逻辑放在中间件中处理,可以使得应用程序具有更好的可扩展性、灵活性和可维护性。

设计模式则是一套被广泛应用于软件开发中的经验总结。

它们是针对软件开发中常见问题的解决方案,可以帮助开发人员更好地组织和设计代码。

设计模式可以提高代码的可读性、可扩展性和可重用性,同时也能够降低代码的复杂度。

在中间件体系结构中,设计模式发挥着重要的作用。

设计模式能够帮助开发人员更好地设计和组织中间件的功能和服务。

下面介绍几个常见的中间件体系结构中使用的设计模式:1.装饰器模式:装饰器模式允许在不修改原有对象的情况下,动态地给对象添加额外的功能。

在中间件体系结构中,装饰器模式可以用于给中间件添加特定的功能,比如日志记录、性能监控等。

2.观察者模式:观察者模式用于建立一种对象之间的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会收到通知。

在中间件体系结构中,观察者模式可以用于实现消息传递机制,当一个消息发送时,所有订阅该消息的组件都可以收到通知。

3.工厂模式:工厂模式用于创建对象的过程,通过将对象的创建从具体的类中分离出来,使得代码更加灵活和可扩展。

在中间件体系结构中,工厂模式可以用于动态地创建中间件对象,根据不同的配置和需求创建不同的中间件实例。

4.责任链模式:责任链模式用于将请求的发送者和接收者解耦,并且允许多个对象都有机会处理该请求。

在中间件体系结构中,责任链模式可以用于处理请求的传递和处理过程,将请求传递给适合处理的中间件组件。

5.适配器模式:适配器模式用于将一个类的接口转换成客户端期望的另一个接口。

在中间件体系结构中,适配器模式可以用于适配不同的中间件协议或接口,使得不同的中间件组件能够协同工作。

总结起来,中间件体系结构和设计模式的结合可以使得系统的各个组件能够高效地协同工作。

软件设计模式中的桥接模式与装饰器模式比较

软件设计模式中的桥接模式与装饰器模式比较

软件设计模式中的桥接模式与装饰器模式比较桥接模式和装饰器模式是软件设计中常用的两种设计模式,它们都属于结构型模式,但在使用和实现上有一些不同之处。

本文将对这两种模式进行比较。

首先,桥接模式和装饰器模式的目的不同。

桥接模式的目的是将抽象部分与它的具体实现部分分离,使它们可以独立变化,而装饰器模式则是在不改变原对象的基础上,动态地给该对象添加一些额外的职责。

其次,在桥接模式中,抽象部分与实现部分可以独立地变化。

通过桥接模式,我们可以在不修改原有代码的情况下,对抽象部分和实现部分进行扩展。

而在装饰器模式中,装饰器可以动态地对对象进行功能的扩展和修改,但是它们的调用顺序是固定的,且装饰器与被装饰者之间存在一种固定的关系。

此外,在桥接模式中,抽象部分和实现部分是通过一个桥接接口来进行关联的。

这个桥接接口定义了抽象部分和实现部分的关联方法。

而在装饰器模式中,装饰器与被装饰者之间的关联是通过继承和组合来实现的。

在实现上,桥接模式通常使用接口和抽象类来定义抽象部分和实现部分,并通过组合来将两者关联起来。

而装饰器模式则是通过继承来实现对被装饰者的功能扩展。

在使用上,桥接模式适用于系统中存在多个变化维度的场景,通过桥接模式可以在每个变化维度上进行扩展和变化,提高系统的灵活性。

而装饰器模式适用于需要给对象动态地添加或修改功能的场景,通过装饰器可以避免使用继承带来的静态特性,使得系统更加灵活和可扩展。

综上所述,桥接模式和装饰器模式在使用和实现上有一些不同之处。

桥接模式主要用于抽象部分和实现部分的分离,而装饰器模式主要用于对对象功能的扩展和修改。

在实际开发中,我们可以根据具体的需求选择合适的模式来解决问题。

编程中的设计模式:8个常见模式解析

编程中的设计模式:8个常见模式解析

编程中的设计模式:8个常见模式解析设计模式是软件开发中常见的一种解决问题的思想模式,它是一种经过多次实践总结出来的在特定情境下,对特定问题的解决方案。

设计模式通过将经典的经验进行抽象,然后形成模式来指导软件开发工程师进行设计和开发。

下面将介绍8个常见的设计模式。

1.工厂模式(Factory Pattern)工厂模式是一种创建型模式,用于创建对象的过程中隐藏了具体的实现细节,只暴露了一个工厂类的接口。

工厂模式可以根据不同的参数或条件,动态地返回不同的具体对象,达到解耦的效果,提高了代码的灵活性和可维护性。

2.单例模式(Singleton Pattern)单例模式是一种创建型模式,保证一个类只有一个实例,并提供全局访问点,同时对外部隐藏了具体的创建过程。

单例模式可以用于实现全局资源的管理,例如线程池、数据库连接等,避免了资源的创建和销毁过程中的开销问题。

3.观察者模式(Observer Pattern)观察者模式是一种行为型模式,定义了一种一对多的依赖关系,使得当一个对象的状态发生变化时,其相关依赖对象都能够得到通知和更新。

观察者模式可以实现松耦合的通信方式,增加了对象之间的交互性,提高了系统的可扩展性和可维护性。

4.策略模式(Strategy Pattern)策略模式是一种行为型模式,定义了一系列算法或行为,将它们封装起来并可以相互替换。

策略模式使得算法的变化不会影响到调用算法的客户端,提高了代码的可复用性和可维护性。

5.装饰器模式(Decorator Pattern)装饰器模式是一种结构型模式,可以动态地给一个对象添加一些额外的职责,而无需对原始对象进行修改。

装饰器模式通过组合的方式,将一系列装饰器对象包裹在被装饰对象的外部,从而在运行时动态地扩展对象的功能。

6.适配器模式(Adapter Pattern)适配器模式是一种结构型模式,用于将一个类的接口转换成客户端所期望的接口。

适配器模式中,适配器类是作为两个不兼容的接口之间的桥梁,将一个类的接口转换成另一个接口,从而可以让它们能够正常地协同工作。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

OO原则
• • • • •
封装变化 多用组合,少用继承 针对接口编程,不针对实现编程 为交互对象之间的松耦合设计而努力 对扩展开放,对修改关闭
Any Question ????
Thank you
测试你的新Java I/O装饰者
要点
• 继承属于扩展形式之一,但不见得是达到弹性设计 的最佳方式 • 在我们的设计中,应该允许行为可以被扩展,而无 须修改现有的代码 • 组合和委托可用于在运行时动态地加上新的行为 • 除了继承,装饰者模式也可以让我们扩展行为 • 装饰者模式意味着一群装饰者类, 这些类用来包 装具体组件 • 装饰者类反映出被装饰的组件类型(事实上,他们 具有相同的类型,都经过接口或继承实现)

现在,该是为顾客算钱的时候了。通过调用最外 圈装饰者(Whip)的cost()就可以办得到。Whip 的cost()会先委托它装饰的对象(也就是Mocha) 计算出价钱,然后再加上奶泡的价钱。
这是目前所知道的一切…… 这是目前所知道的一切
• • • 装饰者和被装饰对象有相同的超类型 你可以用一个或多个装饰者包装一个对象 既然装饰者和被装饰对象有相同的超类型,所 以在任何需要原始对象(被包装的)的场合, 可以用装饰过的对象代替它 装饰者可以在所委托被装饰者的行为之前与/或
认识装饰者模式
• 我们已经了解利用继承无法完全解决问题,在星 巴兹遇到的问题有:类数量爆炸、设计死板,以 及基类加入的新功能并不适用于所有的子类 • 所以,在这里要采用不一样的做法:我们要以饮 料为主体,然后在运行时以调料来“装饰” (decorate)饮料
• 比方说,如果顾客想要摩卡和奶泡深焙咖啡,那 么,要做的是:
} }
} }
public class DarkRoast extends Beverage { public DarkRoast() { description = “Most Excellent Dark Roast”; } public double cost() { return 1.99 + super.cost(); } }
习题解答
真实世界的装饰者: 真实世界的装饰者:Java I/O
装饰java.io类 类 装饰
编写自己的Java I/0装饰者
• 编写一个装饰者,把输入流内的所有大写字符转 成小写 • 举例:当读取“I know the Decorator Pattern therefore I RULE!”,装饰者会将它转成“i know the decorator pattern therefore i rule!”
写下星巴兹的代码

先从Beverage类下手,这不需要改变星巴兹原 始的设计。如下所示: 代码清单

让我们也来实现Condiment(调料)抽象类, 也就是装饰者类: 代码清单
写饮料的代码
• • •
现在,已经有了基类,让我们开始开始实现 一些饮料 先从浓缩咖啡(Espresso)开始 我们还需要为具体的饮料设置描述,而且还 必须实现cost()方法
• 尽管继承威力强大,但是体会到它并不总是 能够实现最有弹性和最好维护的设计 • 不通过继承又能如何达到复用呢?
– 利用组合(composition)和委托(delegation) 可以在运行时具有继承行为的效果 – 利用继承设计子类的行为,是在编译时静态决定 的,而且所有的子类都会继承到相同的行为。然 而,如果能够利用组合的做法扩展对象的行为, 就可以在运行时动态地进行扩展
– – – – 拿一个深焙咖啡(DarkRoast)对象 以摩卡(Mocha)对象装饰它 以奶泡(Whip)对象装饰它 调用cost()方法,并依赖委托(delegate)将调料的价 钱加上去
• 但是如何“装饰”一个对象,而“委托”又要如 何与此搭配使用呢? • 给一个暗示:把装饰者对象当成“包装者”。让 我们看看这是如何工作的……
• 购买咖啡时,也可以要求在其中加入各种调料,例 如:蒸奶(Steamed Milk)、豆浆(Soy)、摩卡 (Mocha,也就是巧克力风味)或覆盖奶泡 • 星巴兹会根据所加入的调料收取不同的费用 • 所以订单系统必须考虑到这些调料部分 • 这是他们的第一个尝试……
• 为什么设计这么多类呀? • 利用实例变量和继承,就可以追踪这些调料 • 先从Beverage基类下手,加上实例变量代表是否加 上调料(牛奶、豆浆、摩卡、奶泡……) ……
请为下面类的cost()方法书写代码(用伪 方法书写代码( 请为下面类的 方法书写代码 Java代码即可) 代码即可) 代码即可
public class Beverage { public double cost() {
public class DarkRoast extends Beverage { public DarkRoast() { description = “Most Excellent Dark Roast”; } public double cost() {
以装饰者构造饮料订单
① 以DarkRoast对象开始
② 顾客想要摩卡(Mocha),所以建立一个Mocha 对象,并用它将DarkRoast对象包(wrap)起来

顾客也想要奶泡(Whip),所以需要建立一个Whip装 饰者,并用它将Mocha对象包起来。别忘了, DarkRoast继承自Beverage,且有一个cost()方法,用 来计算饮料价钱。
结构型——装饰器模式(Decorator)
欢迎来到星巴兹咖啡
• 星巴兹(Starbuzz)是以扩张速度最快而闻名的 咖啡连锁店 • 如果你在街角看到它的店,在对面街上肯定还会 看到另一家 • 因为扩张速度实在太快了,他们准备更新订单系 统,以合乎他们的饮料供应要求 • 他们原先的类设计是这样的……
• •
之后,加上自己的行为,以达到特定的目的
对象可以在任何时候被装饰,所以可以在运行 时动态地、不限量地用你喜欢的装饰者来装饰 对象
定义装饰者模式
• •
装饰者模式动态地将责任附加到对象上 若要扩展功能,装饰者提供了比继承更有弹性 的替代方案
装饰我们的饮料
在继承和组合之间,观念有一些混淆
• 有一点混淆……我原以为在这个模式中不会使用继承, 而是要利用组合取代继承 • 看看类图。CondimentDecorator扩展自Beverage类, 这用到了继承 • 的确是如此,但这么做的重点在于,装饰者和被装饰 者必须是一样的类型,也就是有共同的超类,这是相 当关键的地方。在这里,我们利用继承达到“类型匹 配”,而不是利用继承获得“行为” • 为何装饰者需要和被装饰者(亦即被包装的组件)有 相同的“接口”,因为装饰者必须能取代被装饰者 • 但是行为又是从哪里来的? • 当我们将装饰者与组件组合时,就是在加入新的行为。 所得到的新行为,并不是继承自超类,而是由组合对 象得来的
• 将装饰者与组件组合时,就是在加入新的行为。所 得到的新行为,并不是继承自超类,而是由组合对 象得来的 • 继承Beverage抽象类,是为了有正确的类型,而不 是继承它的行为。行为来自装饰者和基础组件,或 与其他装饰者之间的组合关系 • 因为使用对象组合,可以把所有饮料和调料更有弹 性地加以混和与匹配,非常方便。 • 如果依赖继承,那么类的行为只能在编译时静态决 定。换句话说,行如果不是来自超类,就是子类覆 盖后的版本。反之,利用组合,可以把装饰者混合 着用……而且是在“运行时” • 可以在任何时候,实现新的装饰者增加新的行为。 如果依赖继承,每当需要新行为时,还得修改现有 的代码
– 可以利用此技巧把多个新职责,甚至是设计超类 时还没有想到的职责加在对象上。而且,可以不 用修改原来的代码 – 利用组合维护代码。通过动态地组合对象,可以 写新的代码添加新功能,而无须修改现有代码 – 既然没有改变现有代码,那么引进bug或产生意 外副作用的机会将大幅度减少
开放-关闭原则
• 类应该对扩展开放,对修改关闭 • 我们的目标是允许类容易扩展,在不修改现有代 码的情况下,就可搭配新的行为 • 如能实现这样的目标,有什么好处呢? • 这样的设计具有弹性可以应对改变,可以接受新 的功能来应对改变的需求 • 想想观察者模式……通过加入新的观察者,我们 可以在任何时候扩展Subject(主题),而且不 需向主题中添加代码
要点
• 装饰者可以在被装饰者的行为前面与/或后面加上 自己的行为, 甚至将被装饰者的行为整个取代掉, 而达到特定的目的 • 你可以用无数个装饰者包装一个组件 • 装饰者一般对组件的客户是透明的,除非客户程序 依赖于组件的具体类型 • 装饰者会导致设计中出现许多小对象,如果过度使 用,会让程序变得很复杂
代码清单
写调料代码
• 如果回头去看看装饰者模式的类图,将发现 我们已经完成了抽象组件(Beverage),有 了具体组件(HouseBlend),也有了抽象装 饰者(CondimentDecorator) 现在,我们就来实现具体装饰者。先从摩卡 巴兹的朋友决定开始在菜单上加上咖啡 的容量大小,供顾客可以选择小杯(tall)、中杯 (grande)、大杯(venti) • 星巴兹认为这是任何咖啡都必须具备的,所以在 Beverage类中加上了getSize()与setSize() • 他们也希望调料根据咖啡容量收费,例如:小中 大杯的咖啡加上豆浆,分别加收0.10、0.15、 0.20美金 • 如何改变装饰者类应对这样的需求?
潜在的问题 • 当哪些需求或因素改变时会影响这个设计?
– 调料价钱的改变会使我们更改现有代码 – 一旦出现新的调料,我们就需要加上新的方法, 并改变超类中的cost()方法 – 以后可能会开发出新饮料。对这些饮料而言(例 如:冰茶),某些调料可能并不适合,但是在这 个设计方式中,Tea(茶)子类仍将继承那些不 适合的方法,例如:hasWhip()(加奶泡) – 万一顾客想要双倍摩卡咖啡,怎么办?
相关文档
最新文档