设计模式之装饰模式

合集下载

设计模式之装饰模式

设计模式之装饰模式

装饰模式
1.模式定义
动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。

可以对客户透明的方式动态地给一个对象附加上更多的责任。

可以在不需要创建更多子类的情况下,让对象的功能得以扩展。

2.模式结构
装饰模式包含如下角色:
Component: 抽象构件类
ConcreteComponent: 具体构件类
Decorator: 抽象装饰类
ConcreteDecorator: 具体装饰类
3.模式优缺点
装饰模式优点:
(1)对于扩展一个对象的功能,装饰模式比继承更加灵活,不会导致类的个数急剧增加(2)可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为
(3)可以对一个对象进行多次装饰
(4)具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,且原有类库代码无须改变,符合开闭原则
缺点:
(1)使用装饰模式进行系统设计时将产生很多小对象,大量小对象的产生势必会占用更多的系统资源,在一定程度上影响程序的性能
(2)比继承更加易于出错,排错也更困难,对于多次装饰的对象,调试时寻找错误可能需
要逐级排查,较为烦琐
4.实例一
变形金刚在变形之前是一辆汽车,它可以在陆地上移动。

当它变成了机器人之后除了能够在陆地上移动之外,还可以说话。

如果需要,还可以变成飞机,除了可以在陆地上移动还可以在天空中飞翔。

实例类图
代码如下:。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

java最常用的六种设计模式及举例

java最常用的六种设计模式及举例

java最常用的六种设计模式及举例设计模式是在软件开发过程中经验总结的一种编码和设计方式,它们可以帮助我们更好地组织代码,提高代码的可维护性和可复用性。

下面是 Java 中最常用的六种设计模式及其举例:1. 单例模式:单例模式确保一个类只有一个实例,并提供一个全局访问点。

典型的例子是 `ng.Runtime` 类,在整个 JVM 中只有一个运行时实例。

2. 工厂模式:工厂模式通过一个工厂类来创建其他类的对象,将对象的创建和使用分离,降低了代码的耦合度。

比如,`java.util.Calendar` 类使用了工厂模式来创建 `Calendar` 对象,其中的 `getInstance()` 方法返回一个 `Calendar` 实例。

3. 观察者模式:观察者模式定义了对象之间的一对多的依赖关系,当一个对象状态发生改变时,其相关依赖对象会收到通知并自动更新。

一个典型的例子是使用 `java.util.Observable` 类和 `java.util.Observer`接口进行监听和通知。

4. 装饰者模式:装饰者模式通过动态地将新功能附加到对象上,为对象提供了灵活的扩展方式,不需要修改原始对象的结构。

比如,`java.io` 包中的各种装饰者类可以用来扩展输入输出功能。

5. 策略模式:策略模式定义了一组算法,并将每个算法封装到可互换的对象中,使得算法的变化不会影响到使用算法的客户端。

一个常见的例子是使用 `parator` 接口来实现不同的比较策略。

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

比如,`java.util.Arrays` 类中的 `asList()` 方法返回的是一个适配器,可以将数组转换成 List。

通过学习这些设计模式,我们可以更好地组织和设计代码,提高代码的可读性和可维护性。

在实际的开发中,我们可以针对具体的需求选择合适的设计模式,并根据需要进行一定的修改和定制。

设计模式(三):“花瓶+鲜花”中的装饰者模式(DecoratorPattern)

设计模式(三):“花瓶+鲜花”中的装饰者模式(DecoratorPattern)

设计模式(三):“花瓶+鲜花”中的装饰者模式(DecoratorPattern)在前两篇博客中详细的介绍了""和“”,今天我们就通过花瓶与鲜花的例⼦来类⽐⼀下“装饰模式”(Decorator Pattern)。

在“装饰模式”中很好的提现了开放关闭原则,即类应该对扩展开放对修改关闭。

装饰者模式可以让我们在不对原来代码的修改的情况下对类进⾏扩展。

这也好⽐我们往花瓶⾥插花,我们在插花的时候是不会对花瓶以及原来的话进⾏任何的修改,⽽只管将我们新的花添加进花瓶即可。

这就是我们的装饰者模式。

当然本篇博客中所采⽤的语⾔仍然是Swift语⾔。

装饰者模式,⽤另⼀种表达⽅式就是“对原有的物体进⾏装饰,给原有的物体添加上新的装饰品”。

举个栗⼦,⽐如⼀个礼物,我们要对其进⾏包装,礼物是被装饰者(我们称为组件---Component),⽽包装盒以及包装盒上的花等等就是装饰品(我们成为装饰者---Decorator)。

如果换成花瓶与鲜花的关系,花瓶就是Component,⽽鲜花就是Decorator。

下⽅引⽤了装饰者模式的定义:装饰者模式:动态地将责任附加到对象上。

若要扩展功能,装饰着提供了⽐继承更有弹性的替代⽅案。

⼀、使⽤“类图”分析鲜花+花瓶的装饰关系与之前博客的风格类似,我们还是依托于实例来理解“装饰者模式”,我们就依托于花瓶与鲜花的关系来理解⼀下装饰者模式。

在之前的博客中我们提到过⼀条设计原则“封装变化”,也就是说要将变化的东西进⾏封装提取。

在“装饰者模式”中所使⽤的装饰就是变化的部分,也就是Decorator是变化的部分对应着我们的鲜花,因为往花瓶中插花的过程就是鲜花变化的过程,也就是为花瓶装饰的过程。

⽽花瓶就是组件了。

在“装饰者模式”中需要注意的是,这⾥所谓的装饰者不单单就是我组件添加的新的装饰品。

⼀个装饰者对象就是添加该装饰后的组件,也就是说装饰者=旧组件 + 新装饰品,理解这⼀点是⾮常重要的。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

装饰模式和代理模式的比较

装饰模式和代理模式的比较

装饰模式和代理模式的比较装饰模式和代理模式是常见的两种设计模式,它们都属于结构型设计模式,但在实际应用中有不同的使用场景和作用。

本文将就这两种模式展开比较,以解决在选择使用哪种模式时的困惑。

1、基础概念装饰模式是指在保持原有对象类结构不变的情况下,根据不同的需求,动态地给一个对象添加一些额外的功能,可以理解为在对象外面包一层装饰器,从而实现了增强对象功能的目的。

代理模式是指使用一个代理类来管理原对象的创建和销毁以及访问控制,代理类与被代理类的接口一致,所以在客户端看来,代理类与原对象是一致的,但是代理类在原对象的基础上增加了一些功能。

2、异同点装饰模式和代理模式在实现方式上较为相似,都是使用了增加功能的方式来实现对原对象的扩展。

但两种模式的目的是不同的,装饰模式是为了增加对象功能,而代理模式是为了对对象访问进行控制。

在使用场景上,装饰模式较为适用于需要在运行时动态增加对象功能的场景,因为它可以根据不同的需求动态地为对象增加功能,从而实现了对象功能的增强。

而代理模式则更适用于需要对对象访问进行控制的场景,例如需要在访问某些对象时进行安全验证等操作,这时代理模式可以很好地实现这些控制需求。

此外,装饰模式和代理模式也在一些细节和实现方式上存在差异。

装饰模式通常需要定义一个抽象装饰类和一个具体装饰类,抽象装饰类用于定义增加功能的接口,具体装饰类则实现这些功能接口并扩展对象功能。

而代理模式则通常使用一个代理类来管理原对象的访问,代理类会建立一个和原对象一样的接口,并在其基础上实现额外的功能。

3、应用场景装饰模式适用于需要在运行时动态增加对象功能的场景,例如在系统中使用了一些基础组件,但在某些场景下需要给这些组件增加一些额外的功能,这时可以使用装饰模式来增加组件的功能。

例如在网上购物系统中,购物车是一个基础组件,但在结算时需要对购物车信息进行汇总、检查和更改,这时可以使用装饰模式来为购物车增加这些功能。

代理模式适用于需要对对象访问进行管理或控制的场景,例如在需要对远程对象进行访问或在系统中需要对对象进行安全验证等操作时,可以使用代理模式。

设计模式.装饰模式(Decorator)

设计模式.装饰模式(Decorator)
需要扩展一个类的行为,但由 于继承为类带来了过多的复杂
性或者继承层次过深。
需要对一组基本功能进行排列 组合以产生非常多的功能,而 使用继承关系很难实现这样的 需求。
需要在不修改现有代码的情况 下对程序进行功能扩展。
02
装饰模式的实现方式
继承实现方式
1 2 3
优点
代码简洁,易于理解。
缺点
不够灵活,每增加一个新的装饰功能,都需要创 建一个新的子类,类数量会急剧增加,导致系统 庞大和复杂。
03 需要对一组基本功能进行排列组合以产生非常多 的功能。
对未来研究的展望
深入研究装饰模式的适用场 景和最佳实践,以便更好地 应用该模式解决实际问题。
研究如何将装饰模式与其 他设计模式结合使用,以 产生更好的设计效果。
ABCD
探索如何降低装饰模式的 复杂性,提高代码的可读 性和维护性。
关注新兴技术和编程语言对装 饰模式的影响,以便及时调整 和更新该模式的应用方式。
可能破坏封装性
在使用装饰模式时,需要注意不要破坏对象的封 装性。如果装饰器暴露了对象的内部状态或实现 了不应该暴露的方法,那么可能会导致系统的不 稳定性和安全性问题。
06
总结与展望
对装饰模式的总结
优点 装饰模式可以在不改变对象自身的基础上,动态地给对象添加一些额外的职责。
装饰模式可以在运行时选择性地添加或删除某些功能,提高了系统的灵活性。
统或类的整合和简化。
03
透明性不同
装饰模式对客户端是透明的,客户端可以无感知地使用被装饰的对象,
而外观模式则可能需要对客户端进行一定的定制,以提供简化的接口。
与桥接模式的比较
目标不同
装饰模式的目标是动态地给一个对象添加一些额外的职责, 而桥接模式的目标是将抽象部分与它的实现部分分离,使 它们都可以独立地变化。

Java设计模式菜鸟系列(三)装饰者模式建模与实现

Java设计模式菜鸟系列(三)装饰者模式建模与实现

Java设计模式菜鸟系列(三)装饰者模式建模与实现装饰者(Decorator)模式:动态地将责任附加到对象上。

若要扩展功能,装饰者提供了⽐继承更具有弹性的替代⽅案。

对于装饰者模式,它事实上是⼀种包装。

所以我更愿意称它为⼀种包装。

像咱们曾经常常使⽤的Java⾥⾯的IO流就⽤到了装饰者模式。

⽐⽅:BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file1)));这⾥file1为⽬标对象,⽽像BufferedReader、InputStreamReader就能够称之为包装类。

以下举例说明:⼀、UML模型图⼆、代码实现/*** 对改动关闭,对扩展开放。

** 统⼀接⼝*/interface Filterable {public void filter();}/*** ⽬标类*/class Filter implements Filterable {@Overridepublic void filter() {System.out.println("⽬标类的核⼼过滤⽅法...");}}/*** DecoratorForFilter1包装类与⽬标类实现同样的接⼝ --> 织⼊Log*/class DecoratorForFilter1 implements Filterable {private Filterable filterable;public DecoratorForFilter1(Filterable filterable) {this.filterable = filterable;}private void beforeMethod() {System.out.println("DecoratorForFilter1 --> 核⼼过滤⽅法运⾏前运⾏");}private void afterMethod() {System.out.println("DecoratorForFilter1 --> 核⼼过滤⽅法运⾏后运⾏");}@Overridepublic void filter() {beforeMethod();filterable.filter();afterMethod();}}/*** DecoratorForFilter2包装类与⽬标类实现同样的接⼝ --> 织⼊Log*/class DecoratorForFilter2 implements Filterable {private Filterable filterable;public DecoratorForFilter2(Filterable filterable) {this.filterable = filterable;}private void beforeMethod() {System.out.println("DecoratorForFilter2 --> 核⼼过滤⽅法运⾏前运⾏");}private void afterMethod() {System.out.println("DecoratorForFilter2 --> 核⼼过滤⽅法运⾏后运⾏");}@Overridepublic void filter() {beforeMethod();filterable.filter();afterMethod();}}/*** client測试类** @author Leo*/public class Test {public static void main(String[] args) {/*** ⽬标对象*/Filterable targetObj = new Filter();/*** 包装对象(对⽬标对象进⾏包装)*/Filterable decorObj = new DecoratorForFilter1(new DecoratorForFilter2(targetObj));/*** 运⾏包装后的业务⽅法*/decorObj.filter();}}输出:DecoratorForFilter1 --> 核⼼过滤⽅法运⾏前运⾏DecoratorForFilter2 --> 核⼼过滤⽅法运⾏前运⾏⽬标类的核⼼过滤⽅法...DecoratorForFilter2 --> 核⼼过滤⽅法运⾏后运⾏DecoratorForFilter1 --> 核⼼过滤⽅法运⾏后运⾏三、应⽤场景(仅代表个⼈观点)I/O、过滤器四、⼩结通过输⼊的Log我们能够看到:输出的过程事实上是将包装类“拆包”的过程,就像包装袋⼀样⼀层⼀层的拆开。

装饰模式和职责链模式的对比

装饰模式和职责链模式的对比

装饰模式和职责链模式的对比在软件开发中,设计模式是一个十分重要的概念,是指在软件设计过程中可以重复使用的解决问题的方案。

其中,装饰模式和职责链模式都是常见的设计模式,本文将对这两种模式进行比较分析。

一、装饰模式装饰模式,是指在不改变现有对象的基础上,动态地添加一些新的功能。

这种模式通过创建一个包装对象,也可以叫做装饰器来实现。

在装饰器模式中,有三个主要角色,分别是抽象构件(Component)、具体构件(ConcreteComponent)和装饰器(Decorator)。

其中,抽象构件角色定义了抽象接口,具体构件角色实现抽象接口,而装饰器角色继承了抽象构件角色,并持有一个具体构件的实例,起到包装的作用。

装饰模式的优点是可以动态地添加或删除功能,而且可以从不同的角度来扩展一个类的功能,避免了继承带来的代码复杂性和类爆炸问题。

但缺点是装饰层数过多会增加程序的复杂度,也可能会导致增加了过多的类。

二、职责链模式职责链模式,是指通过建立一个请求的处理链,并且每个节点都有处理请求的机会,直到请求被处理完成。

这种模式拥有很强的扩展性,可以根据需要动态地改变请求的处理流程。

在职责链模式中,有两个主要角色,分别是处理者(Handler)和请求(Request)。

处理者是职责链上的节点,每个处理者都可以处理请求,如果请求不能被当前处理者处理,则将请求传递给下一级处理者。

请求则封装了请求的内容和需要执行的操作。

职责链模式的优点是将请求发送者和接收者解耦,可以动态地改变请求的处理流程,可以避免请求发送者和处理者之间的紧耦合关系。

但缺点是会导致请求的处理延迟,也需要合理设计职责链的节点顺序,避免请求被一直传递下去。

三、装饰模式和职责链模式的比较1. 功能不同装饰模式是为对象动态地添加功能,而职责链模式则是为了解耦并且动态地改变请求的处理流程。

2. 使用场景不同装饰模式适用于需要动态地添加或删除功能的场景,也适用于不想使用继承或希望从不同角度扩展类功能的场景。

解析设计模式中的装饰器模式

解析设计模式中的装饰器模式

解析设计模式中的装饰器模式设计模式中的装饰器模式是一种常见的结构型设计模式,它可以动态地为对象添加额外的行为或职责,而又不需要对其进行修改。

本文将解析装饰器模式的定义、特点、实现以及应用场景。

一、定义装饰器模式,又称为包装器模式,是指在不改变已有对象的基础上,动态地添加一些功能的一种设计模式。

通过将对象包装在一个装饰类中,可以在运行时动态地为其添加新的行为和职责。

这种模式能够在不改变原有代码的情况下,非常方便地扩展和修改一个对象的功能。

二、特点装饰器模式的主要特点包括:1. 能够动态地为对象添加新的职责。

2. 装饰器模式通过继承或接口实现,可以让客户端按照自己的需求,动态地组合对象。

3. 装饰器模式可以避免在对象上添加过多的特定职责,降低代码复杂度。

三、实现装饰器模式通过对对象嵌套的方式来动态地增加功能,从而不需要修改已有的代码。

在实现装饰器模式时,通常会定义一个基类或接口,用于表示被装饰的对象,然后定义一个装饰器类,用于扩展被包装对象的功能。

具体实现过程中,可以使用下面这个示例代码:interface Component {operation(): string;}class ConcreteComponent implements Component {public operation(): string {return 'Component';}}class Decorator implements Component {protected component: Component;constructor(component: Component) {ponent = component;}public operation(): string {return ponent.operation();}}class ConcreteDecoratorA extends Decorator {public operation(): string {return `ConcreteDecoratorA(${super.operation()})`;}}class ConcreteDecoratorB extends Decorator {public operation(): string {return `ConcreteDecoratorB(${super.operation()})`;}}在上面的代码中,Component是一个接口,ConcreteComponent 是Component的一种实现,Decorator是装饰器的基类,ConcreteDecoratorA和ConcreteDecoratorB是具体的装饰器实现。

常见的设计模式及应用场景

常见的设计模式及应用场景

常见的设计模式及应用场景设计模式是软件开发中常用的一种代码组织和重用的技术。

它提供了一种解决问题的方案,能够帮助开发人员有效地解决常见的设计问题,并提供可维护、可扩展和可重用的软件。

下面是一些常见的设计模式及其应用场景。

1. 单例模式(Singleton Pattern):单例模式保证一个类只有一个实例,并提供一个全局访问点。

常用于需要共享资源的对象,例如线程池、日志类等。

2. 工厂模式(Factory Pattern):工厂模式用于创建对象,将对象的创建逻辑与客户端代码分离。

常用于创建复杂的对象或者需要隐藏对象创建过程的场景。

3. 观察者模式(Observer Pattern):观察者模式定义了对象间的一对多关系,使得当一个对象状态改变时,其所有依赖对象都能收到通知并自动更新。

常用于事件处理、消息通知等场景。

4. 装饰者模式(Decorator Pattern):装饰者模式在不改变对象原有结构的基础上,动态地为对象添加新的功能。

常用于增强对象的功能或者修改对象的外观。

5. 策略模式(Strategy Pattern):策略模式定义了一系列算法,并将每个算法都封装起来,使得它们可以相互替换。

常用于根据不同的条件选择不同的算法。

6. 适配器模式(Adapter Pattern):适配器模式将一个类的接口转换成另一个接口,以满足客户端的需求。

常用于将不兼容的接口进行适配。

7. 外观模式(Facade Pattern):外观模式提供一个统一的接口,用于访问子系统的一群接口。

常用于简化复杂的子系统调用。

命令模式将一个请求封装成一个对象,使得可以用不同的请求对客户进行参数化。

常用于实现撤销、重做、任务队列等功能。

9. 建造者模式(Builder Pattern):建造者模式通过将复杂对象的构建逻辑与对象本身分离,使得同样的构建过程可以创建不同的表示。

常用于创建复杂的对象。

10. 模板方法模式(Template Method Pattern):模板方法模式定义了一个操作中的算法框架,把一些步骤推迟到子类实现。

24种设计模式

24种设计模式

24种设计模式Factory Pattern(⼯⼚模式):1. 创建对象的接⼝,封装对象的创建;2. 使具体化类的⼯作延迟到⼦类中。

(维护⼀类对象)AbstractFactory Pattern(抽象⼯⼚模型):该模式将⼀组对象的创建封装到⼀个⽤于创建对象的类中。

(解决的问题:要创建⼀组或者相互依赖的对象)。

Singleton Pattern(单例模式):该模式在⾯向纯粹的⾯向对象的范式中⽤于创建唯⼀的实例,值得注意的是Singleton不能被实例化,因此将其构造函数声明为protected或private类型。

Singleton Pattern经常与Factory Pattern结合使⽤,因为Factory对象只能有⼀个。

Builder Pattern(创建者模式):将⼀个复杂的对象的构建与它的表⽰分离,使得同样的构建构成可以创建不同的表⽰。

如建筑师画图纸,⽽⼯⼈建造房屋。

Prototype Pattern(原型模式):提供⼀个通过已存在对象进⾏新对象创建的接⼝(clone)。

(浅拷贝和深拷贝)Bridge Pattern(桥梁模式):将抽象部分与实现部分分开实现,使他们都可以独⽴地变化,并使⽤组合的⽅式将多维度的抽象⽅法联系在⼀起。

⽐如咖啡分⼩杯、中杯、⼤杯以及加奶和不加奶,则抽象部分为:⼩杯、中杯、⼤杯,⾏为为:加奶和不加奶。

Adapter Pattern(适配器模式):适配就是由“源”到“⽬标”的适配,⽽当中链接两者的关系就是适配器。

它负责把“源”过度到“⽬标”。

将⼀个类的接⼝转换成客户希望的另外⼀个接⼝。

Adapter模式使得原本由于接⼝不兼容⽽不能⼀起⼯作的那些类可以⼀起⼯作。

适配器模式分为两种:①⾯向类的设计模式;②⾯向对象的设计模式。

①⾯向类的适配器:该模式使⽤继承和接⼝实现的⽅式复⽤需要适配器的类。

②⾯向对象的适配器:该模式使⽤组合的⽅式实现需要复⽤的类。

Decorator模式(装饰模式):动态地给⼀个对象添加⼀些额外的职责。

设计模式之装饰模式(Decorator)详解及代码示例

设计模式之装饰模式(Decorator)详解及代码示例

设计模式之装饰模式(Decorator)详解及代码⽰例⼀、装饰模式的定义 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加⼀些职责(即增加其额外功能)的模式,它属于对象结构型模式。

⼆、装饰模式优缺点 装饰(Decorator)模式的主要优点有:采⽤装饰模式扩展对象的功能⽐采⽤继承⽅式更加灵活。

可以设计出多个不同的具体装饰类,创造出多个不同⾏为的组合。

其主要缺点是: 装饰模式增加了许多⼦类,如果过度使⽤会使程序变得很复杂。

三、装饰模式的实现 通常情况下,扩展⼀个类的功能会使⽤继承⽅式来实现。

但继承具有静态特征,耦合度⾼,并且随着扩展功能的增多,⼦类会很膨胀。

如果使⽤组合关系来创建⼀个包装对象(即装饰对象)来包裹真实对象,并在保持真实对象的类结构不变的前提下,为其提供额外的功能,这就是装饰模式的⽬标。

下⾯来分析其基本结构和实现⽅法。

装饰模式主要包含以下⾓⾊。

抽象构件(Component)⾓⾊:定义⼀个抽象接⼝以规范准备接收附加责任的对象。

具体构件(Concrete Component)⾓⾊:实现抽象构件,通过装饰⾓⾊为其添加⼀些职责。

抽象装饰(Decorator)⾓⾊:继承抽象构件,并包含具体构件的实例,可以通过其⼦类扩展具体构件的功能。

具体装饰(ConcreteDecorator)⾓⾊:实现抽象装饰的相关⽅法,并给具体构件对象添加附加的责任。

装饰模式的结构图如图所⽰: 我们先来看看我们通过继承的⽅式新增特性这种实现⽅式,⽐如本例使⽤煎饼果⼦,代码如下:/*** 煎饼*/public class Battercake {protected String getDesc(){return "煎饼";}protected int cost(){return 8;}}/*** 加蛋的煎饼*/public class BattercakeWithEgg extends Battercake {@Overridepublic String getDesc() {return super.getDesc()+" 加⼀个鸡蛋";}@Overridepublic int cost() {return super.cost()+1;}}/*** 加蛋加⾹肠的煎饼*/public class BattercakeWithEggSausage extends BattercakeWithEgg {@Overridepublic String getDesc() {return super.getDesc()+ " 加⼀根⾹肠";}@Overridepublic int cost() {return super.cost()+2;}}public class Test {public static void main(String[] args) {Battercake battercake = new Battercake();System.out.println(battercake.getDesc()+" 销售价格:"+battercake.cost());Battercake battercakeWithEgg = new BattercakeWithEgg();System.out.println(battercakeWithEgg.getDesc()+" 销售价格:"+battercakeWithEgg.cost());Battercake battercakeWithEggSausage = new BattercakeWithEggSausage();System.out.println(battercakeWithEggSausage.getDesc()+" 销售价格:"+battercakeWithEggSausage.cost());}} 最后测试结果为:煎饼销售价格:8煎饼加⼀个鸡蛋销售价格:9煎饼加⼀个鸡蛋加⼀根⾹肠销售价格:11 虽然我们也实现了扩展类的功能,但是继承的⽅式耦合度⾼,并且如果新增会⽆限增加类,如果修改原有类,对后⾯的类影响很⼤,因此如果使⽤装饰模式,代码如下:public class DecoratorPattern{public static void main(String[] args){Component p=new ConcreteComponent();p.operation();System.out.println("---------------------------------");Component d=new ConcreteDecorator(p);d.operation();}}//抽象构件⾓⾊interface Component{public void operation();}//具体构件⾓⾊class ConcreteComponent implements Component{public ConcreteComponent(){System.out.println("创建具体构件⾓⾊");}public void operation(){System.out.println("调⽤具体构件⾓⾊的⽅法operation()");}}//抽象装饰⾓⾊class Decorator implements Component{private Component component;public Decorator(Component component){ponent=component;}public void operation(){component.operation();}}//具体装饰⾓⾊class ConcreteDecorator extends Decorator{public ConcreteDecorator(Component component){super(component);}public void operation(){super.operation();addedFunction();}public void addedFunction(){System.out.println("为具体构件⾓⾊增加额外的功能addedFunction()");}}四、装饰模式的应⽤场景 前⾯讲解了关于装饰模式的结构与特点,下⾯介绍其适⽤的应⽤场景,装饰模式通常在以下⼏种情况使⽤。

装饰模式的应用场景和优势

装饰模式的应用场景和优势

装饰模式的应用场景和优势装饰模式是一种常见的设计模式,在软件开发中得到广泛应用。

它主要用于在不改变原有类的情况下,动态地给对象增加新的功能,从而提高代码的灵活性和可维护性。

本文将介绍装饰模式的应用场景和优势。

一、应用场景1. 动态增加功能装饰模式适用于需要在运行时动态地给对象增加新的功能的情况。

它可以避免在原有类中频繁修改代码,提高代码的可扩展性和可维护性。

比如,在图形界面开发中,经常需要给控件增加新的样式或者功能,此时可以使用装饰模式。

2. 组合对象装饰模式适用于组合对象的情况。

它可以通过递归组合方式,构建出一个具有多种功能的对象。

例如,在Java的AWT中,Panel和ScrollPane就是组合对象,可以通过装饰模式实现。

3. 消除子类的继承装饰模式可以消除子类的继承关系,让类的结构更加简单明了。

当需要给一个类增加新的功能时,如果采用继承,就需要创建一个新的子类。

而使用装饰模式,只需要增加一个新的装饰器类就可以实现功能的扩展。

二、优势1. 可扩展性装饰模式可以很方便地扩展系统的功能,而且扩展时无需修改原有代码。

只需要定义一个新的装饰器类,并将需要扩展的对象作为参数传递给装饰器类即可。

2. 更灵活的功能组合采用装饰模式可以实现更灵活的功能组合。

不同的装饰器可以组合不同的功能,从而实现多样化的效果。

例如,在图形界面中,通过不同的装饰器可以实现按钮的不同样式、大小、颜色等。

3. 保证了开闭原则装饰模式遵循开闭原则,可以很方便地增加新的功能而不影响原有的代码。

因此,它是一个很好的可扩展的设计模式。

4. 降低了类的复杂度使用装饰模式可以避免创建大量的子类,降低类的复杂度,从而使代码更加简单易懂。

三、总结装饰模式是一种很常用的设计模式,适合于需要动态增加对象功能、组合对象、消除继承关系等情况。

它的优势在于可扩展性、更灵活的功能组合、保证开闭原则、降低类的复杂度等方面。

在实际开发中,我们应该充分利用装饰模式,使软件的设计更加灵活、可维护性更高。

设计模式-装饰模式总结及实例

设计模式-装饰模式总结及实例
}
};
class BigTrouser : public Finery
{
pShow()
{
printf("跨裤");
__super::Show();
}
};
class Sneakers : public Finery
{
public:
virtual void Show()
实现方式(UML类图)
实现代码
#include <stdio.h>
class Person
{
public:
Person() : name(0){}
Person(char* _name) : name(_name){}
virtual void Show()
{
printf("装扮的%s",name);
}
virtual void Show()
{
printf("领带");
__super::Show();
}
};
class LeatherShoes : public Finery
{
public:
virtual void Show()
{
printf("皮鞋");
__super::Show();
}
};
int main()
kk->Decorate(pqx);
dtx->Decorate(kk);
dtx->Show();
printf("\n第二种装扮:\n");
LeatherShoes* px = new LeatherShoes();

指责链模式和装饰模式的比较

指责链模式和装饰模式的比较

指责链模式和装饰模式的比较指责链模式和装饰模式是常用的设计模式,它们都可以用来解决问题,但实现方式有所不同。

下面我将介绍它们的特点、优缺点和比较。

一、指责链模式指责链模式是一种行为型模式,它将请求的发送者和接受者解耦,将请求的处理对象组成一条链,由每个对象负责处理请求,直到请求被处理完成。

1. 特点①处理对象之间具有松散耦合性,将处理对象串成一条链,将请求发送到链上的第一个对象,请求在链上传递,直到有一个对象处理请求完成为止,请求发送者和处理者单向关联,请求发送者不知道哪个处理者会处理请求,处理者也不知道请求的发送者是谁。

②通过动态的增加或者删除处理对象,灵活地改变处理链,易扩展、维护,符合开闭原则。

③因为链中的对象有机会处理请求,可以处理一些请求的复杂业务逻辑,分散到不同的处理对象中,解耦复杂业务逻辑。

2. 优缺点(1) 优点:①降低耦合度:请求发送者和接收者之间解耦,使得发送者和接收者不直接依赖。

②简化对象:处理者不需要知道链的结构,只需要知道下一个处理者,方便增加或者删除处理者。

③加强扩展性:可以通过增加处理对象来扩展业务功能。

④灵活性:不同的业务逻辑可以拆分到处理对象中,方便维护。

(2) 缺点:①一般情况下,链条过长会影响性能。

②可能链还没走完,请求已经被处理完,这种情况下,处理效率较低。

二、装饰模式装饰模式也是一种行为型模式,它可以在不改变原有对象的结构和功能,对对象进行动态扩展和修改。

1. 特点①装饰者和被装饰者具有相同的超类型,也就是说,装饰者和被装饰者都具有同样的接口或者类。

②通过动态增加或删除装饰器,对被装饰的对象进行扩展或修改,使得对象具有更多的行为。

③装饰者不改变原有对象的功能,只增加了功能。

2. 优缺点(1) 优点:①可以动态地为对象增加新的功能。

②装饰模式可以提供更加灵活的方式,避免了继承的缺点,比如当需要增加功能时,不需要修改以前的类。

③装饰模式增强了代码的复用性。

(2) 缺点:①装饰模式增加了系统的复杂度。

二十三种设计模式

二十三种设计模式
7、桥梁模式:Bridge
将抽象化与实现化脱耦,使得二者可以独立的变化,也就是说将他们之间的强关联变成弱关联,也就是指在一个软件系统的抽象化和实现化之间使用组合/聚合关系而不是继承关系,从而使两者可以独立的变化。
8、合成模式:Composite
合成模式将对象组织到树结构中,可以用来描述整体与部分的关系。合成模式就是一个处理对象的树结构的模式。合成模式把部分与整体的关系用树结构表示出来。合成模式使得客户端把一个个单独的成分对象和由他们复合而成的合成对象同等看待,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。策略模式把行为和环境分开。环境类负责维持和查询行为类,各种算法在具体的策略类中提供。由于算法和环境独立开来,算法的增减,修改都不会影响到环境和客户端。
3、工厂方法模式:FactoryMethod
核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
4、原始模型模式:Prototype
通过给出一个原型对象来指明所要创建的对象的类型,然后用复制这个原型对象的方法创建出更多同类型的对象。原始模型模式允许动态的增加或减少产品类,产品类不需要非得有任何事先确定的等级结构,原始模型模式适用于任何的等级结构。缺点是每一个类都必须配备一个克隆方法。
20、状态模式:State
状态模式允许一个对象在其内部状态改变的时候改变行为。这个对象看上去象是改变了它的类一样。状态模式把所研究的对象的行为包装在不同的状态对象里,每一个状态对象都属于一个抽象状态类的一个子类。状态模式的意图是让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。

设计模式回顾:策略模式、代理模式、装饰者模式的区别

设计模式回顾:策略模式、代理模式、装饰者模式的区别

设计模式回顾:策略模式、代理模式、装饰者模式的区别前⾔设计模式有很多,但设计模式的⽬的是⼀致的,都是为了提升代码的可读性和可扩展性。

设计模式都遵循⼀些基本的原则,设计模式是为了遵循这些原则⽽创造的⼯具。

- 单⼀职责原则:就⼀个类⽽⾔,应该仅有⼀个引起它变化的原因。

这⼀点是说,如果有⼀些类过于臃肿,承担了过多的职责,就应当分解他。

- 开放-封闭原则:软件实体(类、模块、函数等)应该可以扩展,但是不可修改。

这⼀点是说,拒绝硬编码,拒绝直接修改原有代码。

- 依赖倒转原则:⾼层模块不应该以来低层模块。

两个都应该以来抽象。

抽象不应该依赖细节。

细节应该依赖抽象。

这⼀点是说,应该使⽤⾯向接⼝编程。

这些原则是程序员在协同⼯作中达成的共识,就算⼤家从来没有学习过什么设计模式,只要能遵循这些原则,也许你⾃⼰已经使⽤了某些设计模式。

有三个模式我以前学习的时候很混淆,他们是策略模式、代理模式、装饰者模式。

混淆的原因是,这三个模式都是在辅助类中持有⼀个⽬标类的对象,通过操作这个⽬标对象,完成实际任务。

在⼯作中具体场景下深⼊思考以后,我终于对他们有了进⼀步的理解。

⾸先来看策略模式,uml类图如下策略模式通过将⼀些易变的计算抽象为策略实体,通过多态,让实际调⽤者尽可能的不⽤感知这种变化。

再看代理模式代理模式与策略模式不同的是,代理类必须和被代理类具有相同的⽗类或接⼝,即代理类要么继承或实现被代理类的⽗类,要么直接计程被代理类本⾝。

这两种情况分别对应java的jdk代理和cglib代理实现。

代理模式不是为了封装变化,⽽是为了隐藏实际执⾏者本⾝。

最后是装饰者模式装饰者模式和策略模式的不同在于,原有类和装饰器类必须继承同⼀个⽗类。

装饰器对象除了需要完成持有对象的操作外,还有⼀些附加操作,这些附加操作随着装饰器的不同⽽变化。

持有对象本⾝的操作是主体,装饰器的操作是补充。

⽽策略模式中,具体策略才是主体。

C#设计模式系列:装饰模式(Decorator)

C#设计模式系列:装饰模式(Decorator)

C#设计模式系列:装饰模式(Decorator)1. 装饰模式简介 装饰模式动态地给⼀个对象添加额外的职责。

例如⼀幅画有没有画框都可以挂在墙上,画就是被装饰者。

但是通常都是有画框的。

在挂在墙上之前,画可以被蒙上玻璃,装到框⼦⾥,所以在画上加⼀层画框,并把它们组合成⼀个整体——有框的画。

这样随着不断有新的装饰的加⼊,就给商品不断地打上包装,变成⼀个功能更让⼈满意的商品。

这种不断打包装的过程就是装饰。

1.1 定义 装饰模式提供了⼀种给类增加功能的⽅法。

它通过动态地组合对象,可以给原有的类添加新的代码,⽽⽆须修改现有代码。

因此引⼊bug或产⽣意外副作⽤的机会将⼤幅度减少。

1.2 使⽤频率 中等2. 装饰模式结构图2.1 结构图2.2 参与者 装饰模式参与者: ◊ Component:定义⼀个对象接⼝,可以给这些对象动态地添加职责 ◊ ConcreteComponent:定义⼀个对象,可以给这个对象添加⼀些职责 ◊ Decorator:维持⼀个指向Component的指针,并定义⼀个与Component接⼝⼀致的接⼝ ◊ ConcreteDecorator:负责向ConcreteComponent添加功能 在装饰模式中,Decorator定义了⼀个装饰接⼝类。

因为Decorator与ConcreteComponent继承同⼀个接⼝,所以继承Decorator的类ConcreteDecorator可以使⽤ConcreteComponent的⽅法,再在ConcreteDecorator⾥⾯加⼊⼀些新的⽅法,也就是装饰,就成为了⼀个包装好的装饰类。

3、装饰模式结构实现 Component.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.DecoratorPattern.Structural{public abstract class Component{public abstract void Operation();}} ConcreteComponent.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.DecoratorPattern.Structural{public class ConcreteComponent : Component{public override void Operation(){Console.WriteLine("ConcreteComponent.Operation()");}}} Decorator.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.DecoratorPattern.Structural{public abstract class Decorator : Component{protected Component component;public void SetComponent(Component component){ponent = component;}public override void Operation(){if (component != null){component.Operation();}}}} ConcreteDecoratorA.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.DecoratorPattern.Structural{public class ConcreteDecoratorA : Decorator{public override void Operation(){base.Operation();Console.WriteLine("ConcreteDecoratorA.Operation()"); }}} ConcreteDecoratorB.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;namespace DesignPatterns.DecoratorPattern.Structural{public class ConcreteDecoratorB : Decorator{public override void Operation(){base.Operation();AddedBehavior();Console.WriteLine("ConcreteDecoratorB.Operation()"); }void AddedBehavior(){}}} Program.csusing System;using System.Collections.Generic;using System.Linq;using System.Text;using DesignPatterns.DecoratorPattern.Structural; namespace DesignPatterns.DecoratorPattern{class Program{static void Main(string[] args){// Create ConcreteComponent and two DecoratorsConcreteComponent c = new ConcreteComponent();ConcreteDecoratorA d1 = new ConcreteDecoratorA();ConcreteDecoratorB d2 = new ConcreteDecoratorB();// Link decoratorsd1.SetComponent(c);d2.SetComponent(d1);d2.Operation();}}} 运⾏输出:ConcreteComponent.Operation()ConcreteDecoratorA.Operation()ConcreteDecoratorB.Operation()请按任意键继续. . .4、装饰模式应⽤分析 装饰模式适⽤情形: ◊ 在不影响其他对象的情况下,以动态、透明的⽅式给单个对象添加职责 ◊ 处理那些可以撤销的职责 装饰模式的特点: ◊ ⽐静态类更灵活。

系统设计设计模式中的代理模式与装饰器模式

系统设计设计模式中的代理模式与装饰器模式

系统设计设计模式中的代理模式与装饰器模式系统设计中的代理模式与装饰器模式代理模式和装饰器模式都是系统设计中常用的设计模式,在不同的场景中起到了不同的作用。

本文将介绍代理模式和装饰器模式的概念、应用场景以及它们之间的区别。

一、代理模式的概念和应用场景代理模式是指通过一个代理类来控制对实际对象的访问,客户端通过代理类来间接地访问实际对象,从而可以对实际对象进行控制和管理。

代理模式的主要特点是可以在客户端和实际对象之间进行一些额外的处理,而对客户端来说,它并不知道实际对象的存在。

代理模式的应用场景非常广泛,例如:1. 远程代理:在网络通信中,通过代理类可以实现客户端和服务端的通信;2. 虚拟代理:在创建对象的过程中,可以通过代理类来替代实际对象,从而减少对象的创建和销毁;3. 安全代理:在访问对象时,可以通过代理类来进行权限控制,确保只有满足条件的用户才能访问对象;4. 延迟加载:在访问对象时,可以通过代理类来实现延迟加载,只有在真正需要对象时才进行加载。

二、装饰器模式的概念和应用场景装饰器模式是指在不改变对象的基础上,通过对对象进行包装,来扩展对象的功能。

装饰器模式的主要特点是可以动态地给对象添加新的功能,而不会影响到其他对象。

装饰器模式的应用场景也非常广泛,例如:1. 扩展功能:通过装饰器模式可以给对象添加一些额外的功能,而不需要修改对象的结构;2. 动态代理:通过装饰器模式可以对对象进行动态代理,实现对方法的调用前后进行一些额外的操作;3. 缓存功能:通过装饰器模式可以给对象添加缓存功能,提高系统的性能;4. 日志记录:通过装饰器模式可以给对象添加日志记录功能,方便系统的调试和错误追踪。

三、代理模式与装饰器模式的区别尽管代理模式和装饰器模式在功能上有些相似,但它们之间有一些区别:1. 目的不同:代理模式的主要目的是控制对实际对象的访问,而装饰器模式的主要目的是扩展对象的功能。

2. 关注点不同:代理模式关注的是对实际对象的访问控制和管理,而装饰器模式关注的是给对象添加新的功能。

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

设计模式之装饰模式装饰模式非常强调实现技巧,我们一般用它应对类体系快速膨胀的情况。

在项目中,是什么原因导致类型体系会快速膨胀呢?在多数情况下是因为我们经常要为类型增加新的职责(功能),尤其在软件开发和维护阶段,这方面需求更为普遍。

面向对象中每一个接口代表我们看待对象的一个特定方面。

在Java编码实现过程中由于受到单继承的约束,我们通常也会将期望扩展的功能定义为新的接口,进而随着接口不断增加,实现这些接口的子类也在快速膨胀,如新增3个接口的实现,就需要8个类型(包括MobileImpl),4个接口则是16个类型,这种几何基数的增长我们承受不了。

为了避免出现这种情况,之前我们会考虑采用组合接口的方式解决,但客户程序又需要从不同角度看待组合后的类型,也就是可以根据里氏替换原则用某个接口调用这个子类。

所以面临的问题是,既要has a、又要is a,装饰模式解决的就是这类问题。

经典回顾装饰模式的意图非常明确:动态为对象增加新的职责。

这里有两个关键词:动态和增加,也就是说,这些新增的功能不是直接从父类继承或是硬编码写进去的,而是在运行过程中通过某种方式动态组装上去的。

例如:我们在录入文字的时候,最初只需要一个Notepad功能的软件,然后增加了很多需求:字体可以加粗。

文字可以显示为不同颜色。

字号可以调整。

字间距可以调整。

……不仅如此,到底如何使用这些新加功能,需要在客户使用过程中进行选择,也就是说,新的职责(功能或成员)是需要动态增加的。

为了解决这类问题,装饰模式给出的解决方案如图12-1所示。

根据Notepad的示例要求,设计如图12-2所示的静态结构。

区别于经典装饰模式设计,在图12-2中我们将Decorator定义为具体类,而不是抽象类,主要是为了简化示例结构。

首先,我们需要的是显示文字,这时可以指定一个名为Text的接口,它有名为Content的读/写属性。

然后,我们把所有需要用来装饰的类型抽象出一个名为Decorator的接口,它继承自这个Text,因此其实体类必须实现Content属性方法。

接着,我们把没有任何新增功能的Text做出一个“毛坯”的实体类型,命名为TextImpl。

最后,我们把操作字体bold()、setColor()的方法填充到每个具体的装饰类型中。

这样,概念上当TextImpl需要某种新增功能时,直接为其套上某个具体装饰类型就可以了。

这就好像给TextImpl类穿上一层又一层的“马甲”。

该模式这么做主要是为了适用于哪些情景呢?在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

毕竟客户程序依赖的仅仅是Component接口,至于这个接口被做过什么装饰,只有实施装饰的对象才知道,而客户程序只是依据Component的接口方法调用它,这样,装饰类在给Component穿上新“马甲”的同时也会随着客户程序的调用一并执行了。

屏蔽某些职责,也就是在套用某个装饰类型时,并不增加新的特征,只把既有方法屏蔽。

也就是说,装饰类不仅能否充当“马甲”,也能起到“口罩”的作用,让Component 现有的某些方法“闭嘴”。

尽管我们使用装饰模式一般是为了增加功能(做“加法”),但并不排斥它也具有方法屏蔽的作用(做“减法”),只不过平时用的比较少而已。

避免因不断调整职责导致类型快速膨胀的情况。

下面看一段示例代码:Java抽象部分publicinterface Text {String getContent();void setContent(String content);}/**implements Text说明Decoratoris a Text*/ publicclass Decoratorimplements Text{/** 构造方式注入has a的text接口*/ private Text text;public Decorator(Text text){this.text = text;}@Overridepublic String getContent(){return text.getContent();}@Overridepublic void setContent(String content){ text.setContent(content);}}Java具体装饰类型/*** 具体装饰类,属于“马甲”*/class BoldDecorator extends Decorator{public BoldDecorator(Text text){super(text);}public String bold(String data){return "<b>" + data +"</b>";}@Overridepublic String getContent() {return bold(super.getContent());}@Overridepublic void setContent(Stringcontent) { super.setContent(content);}}/*** 具体装饰类* 属于“马甲”*/class ColorDecorator extends Decorator{public ColorDecorator(Text text){ super(text);}public String setColor(String data){ return "<color>" + data +"</color>";}@Overridepublic String getContent() {return setColor(super.getContent());}@Overridesuper.setContent(content);}}/*** 具体装饰类* 属于“口罩”*/class BlockAllDecorator extends Decorator{public BlockAllDecorator (Text text){ super(text);}@Overridepublic String getContent() {return null;}@Overridesuper.setContent(content);}}Unit TestTexttext;@Beforepublic void setUp(){text = new TextImpl();}/**验证套用单个装饰对象的效果*/@Testpublic void testSingleDecorator(){text = new Decorator(text);//下面开始套用装饰模式,开始给text穿“马甲”text = new BoldDecorator(text);text.setContent("H");assertEquals("<b>H</b>",text.getContent());}/**验证套用多个装饰对象的效果*/@Testpublic void testMultipleDecorators(){text = new Decorator(text);//下面开始套用装饰模式,开始给text穿“马甲”text = new BoldDecorator(text);text = new ColorDecorator(text);text = new BoldDecorator(text);text.setContent("H");assertEquals("<b><color><b>H</b></color></b>",text.getContent()); }/**验证装饰类型的撤销(/“口罩”)效果*/@Testpublic void testBlockEffectDecorator(){text = new Decorator(text);//下面开始套用装饰模式,开始给text穿“马甲”text = new BoldDecorator(text);text = new ColorDecorator(text);text.setContent("H");assertEquals("<color><b>H</b></color>",text.getContent());//下面开始套用装饰模式,开始给text戴“口罩”text = new BlockAllDecorator(text);assertNull(text.getContent());}从上面的示例中不难看出,装饰模式实现上特别有技巧,也很“八股”,它的声明要实现Component定义的方法,但同时也会保留一个对Component的引用,Component接口方法的实现其实是通过自己保存的Component成员完成的,而装饰类只是在这个基础上增加一些额外的处理。

而且,使用装饰模式不仅仅是为了“增加”新的功能,有时候我们也用它“撤销”某些功能。

项目中我们有3个要点必须把握:Component不要直接或间接地使用Decorator,因为它不应该知道Decorator的存在,装饰模式的要义在于通过外部has a + is a的方式对目标类型进行扩展,对于待装饰对象本身不应有太多要求。

Decorator也仅仅认识Component。

抽象依赖于抽象、知识最少。

某个ConcreteDecorator最好也不知道ComponentImpl的存在,因为ConcreteDecorator只能服务于这个ComponentImpl(及其子类)。

此外,使用装饰模式解决一些难题的同时,我们也要看到这个模式的缺点:开发阶段需要编写很多ConcreteDecorator类型。

运行时动态组装带来的结果就是排查故障比较困难,从实际角度看,Component 提交给客户程序的是最外层ConcreteDecorator的类型,但它的执行过程是一系列ConcreteDecorator处理后的结果,追踪和调试相对困难。

在实际项目中,我们往往会将一些通用的功能做成装饰类型单独编译,而且一般也鼓励这么做,因为可以减少重复开发,但这样会人为增加排查和调试的难度。

好在反编译Java byte code不是太难。

相关文档
最新文档