使用Decorator(装饰)模式改善现有软件设计—运行期给对象添加新功能

[quote]Decorator模式是一种结构型模式,它的作用是动态得给一个对象添加额外职责。Decorator模式,即Wrapper模式,其强制控制作用是在不改动一个类的代码或者不破坏一个类的接口的情况下为该类添加功能。当你想一个类具有更多功能的时候,使用Decorator模式意味着增加功能后的版本不一定要通过扩展类来重用现有功能。[/quote]

Decorator模式绝就绝在动态给对象添加新功能。一般我们使用继承的时候,行为是静态指定的,在没有编译前就指定了继承类(子类)可以做些什么。但是Decorator可以在运行时给定行为,是动态的。Decorator提供了比继承更有弹性的替代方案。

Decorator模式的重点就是类型匹配,装饰者与被装饰者之间必须有相同的超类。所以我们还是得使用继承。使用子类继承抽象基类。[color=red]我们这里去继承抽象类的目的不是为了继承它的行为,目的是为了有正确的类型,也就是类型的匹配。行为来自装饰者和基础组件,或与其它装饰者之间的引用关系。[/color]

为什么装饰者能动态的给对象添加新功能,原因就在这里,一般如果直接继承父类的话,那么我们的行为一定就会在编译之前就已经决定,这样一来,我们根本无法给对象添加新功能,但是使用了装饰者模式,我们又使用了对象与对象之间的组合,之后结果就完全不一样了。我们会写这样的代码:

File file=new File(path);    
BufferedReader br=new BufferedReader(new FileReader(file));


这个代码里面就是把file对象往FileReader里装,之后再把FileReader往BufferedReader装。进行一层一层的装饰。

装饰者模式有一套属于自己的设计思路。如下:


[img]http://dl.iteye.com/upload/attachment/169839/055fd802-abed-303d-a12f-c0a2be987e57.gif[/img]

Component(被装饰对象基类) :定义对象的接口(也可以是抽象类),可以给这些对象动态增加职责;
ConcreteComponent(具体被装饰对象) :定义具体的对象,Decorator可以给它增加额外的职责;
Decorator(装饰者抽象类): 维护一个指向Component实例的引用,并且定义了与Component一致的接口;
ConcreteDecorator(具体装饰者) :具体的装饰对象,给内部持有的具体被装饰对象增加具体的职责;

[quote]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】,还要做人该做的事情,但是可能会对异性更有吸引力了(扩展功能)! [/quote]

以下代码取自《HEAD FIRST 设计模式》。

Beverage还是所有饮料的基类,它对应于装饰者模式类图里的Component,是所有被装饰对象的基类;HouseBlend, DarkRoast, Espresso, Decaf是具体的饮料(咖啡)种类,对应于前面的ConcreteComponent,即是具体的被装饰对象;CondimentDecorator对应于前面的Decorator,是装饰者的抽象类;而Milk,Mocha,Soy,Whip则都是具体的调味品,对于前面的ConcreteDecorator,也就是具体的装饰者。

[img]http://dl.iteye.com/upload/attachment/169849/2da444e7-4c61-3836-8463-b2592062579e.jpg[/img]


package moshi.decorator;

public abstract class Beverage {

public String description="Unknown Beverage";

/*
* getDescription()已经在此实现了,但是cost()必须在子类中实现
*/
public String getDescription() {
return description;
}

public abstract double cost();
}

package moshi.decorator;

public abstract class CondimentDecorator extends Beverage {

//所有的调料装饰者都必须重新实现getDescription()方法.
public abstract String getDescription();

}

package moshi.decorator;

public class Espresso extends Beverage {

public Espresso(){
description="Espresso";
}


public double cost() {
return 1.99;
}

}


package moshi.decorator;

public class HouseBlend extends Beverage {

public HouseBlend(){
description="House Blend Coffee";
}


public double cost() {
return .89;
}

}


package moshi.decorator;

public class Mocha extends CondimentDecorator {

Beverage beverage;

public Mocha(Beverage beverage){
this.beverage=beverage;
}


public String getDescription() {
return beverage.getDescription()+"Mocha";
}


public double cost() {
return .20+beverage.cost();
}

}


package moshi.decorator;

public class Test {

public static void main(String[] args) {
Beverage beverae =new Espresso();
System.out.println(beverae.getDescription()+"$"+beverae.cost());


Beverage beverae1 =new Espresso();
beverae1 =new Mocha(beverae1);
beverae1 =new Mocha(beverae1);
System.out.println(beverae1.getDescription()+"$"+beverae1.cost());
}

}


这段代码很明显,说明了Decorator模式,就从Test类来看。
public static void main(String[] args) {
Beverage beverae =new Espresso();
System.out.println(beverae.getDescription()+"$"+beverae.cost());


Beverage beverae1 =new Espresso();
beverae1 =new Mocha(beverae1);
beverae1 =new Mocha(beverae1);
System.out.println(beverae1.getDescription()+"$"+beverae1.cost());
}


我们一开始只NEW了一个Espresso(),因为Espresso类继承了抽象Beverage类,实现了COST方法,我们自然打印出Espresso的钱。

之后,我们又NEW了一个Espresso(),这下情况有所不一样,我们使用了2个Mocha去往Espresso装饰对象,这里已经说名了下面这段代码为什么要取得Beverage引用。

public class Mocha extends CondimentDecorator {

Beverage beverage;

public Mocha(Beverage beverage){
this.beverage=beverage;
}


public String getDescription() {
return beverage.getDescription()+"Mocha";
}


public double cost() {
return .20+beverage.cost();
}

}


就因为我们取得了beverage,而且 cost()又实现了 return .20+beverage.cost();,自然返回的是Espresso+0.2的值了。


部分内容选自:http://www.cnblogs.com/justinw/archive/2007/06/11/779356.html
Maltab GUI课程设计——网络爬虫程序(基金连涨连跌提醒) 阅读详情

相关推荐

手把手教你用支付宝密钥工具生成RSA2密钥对(含Windows/Mac操作截图)

本文详细介绍了如何使用支付宝密钥工具生成RSA2密钥对,包括Windows和Mac平台的操作步骤与截图。从工具下载、安装到密钥生成、配置支付宝平台,再到开发环境集成实战,手把手教你完成支付宝支付接口对接。特别强调密钥安全管理和最佳实践,帮助开发者避免常见安全隐患。

mongodb5scout的博客 257

第六章 装饰器模式 (Decorator)

装饰模式的定义与特点 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。 装饰(Decorator)模式的主要优点有: 采用装饰模式扩展对象的功能比采用继承方式更加灵活。 可以设计出多个不同的具体装饰类,创造出多个不同行为的组合。 其主要缺点是: 装饰模式增加了许多子类,如果过度使用会使程序变得很复...

JackAtJN的博客 413

潜在图神经网络学习笔记(Latent Graph Neural Networks for Human Skeleton-based Action Recognition)

在本文中,我们从一个新的角度来解决这个问题,通过将非结构化的骨架数据映射到潜在空间,如图2所示,这里称为潜在特征空间或嵌入空间,其中一组项嵌入在一个流形中[ 1 ],并且在潜在空间中彼此更相似的项被放置在彼此更接近的位置。潜在空间中的位置可以被认为是由一组潜在变量定义的,这些潜在变量来源于对象的相似性。将骨架数据嵌入到流形中,消除了远近邻居之间的冗余依赖关系,以解决加权问题。得到具有多尺度聚合特征的稀疏图矩阵结构,以更好地理解骨骼关节的直接加权信息。

qq_45631885的博客 489

设计模式:装饰器模式(为对象动态的添加功能)

前言在学习 Java IO 的时候,记得头几回看到下面的代码,总是有点纳闷: InputStream inputStream = new BufferedInputStream(new FileInputStream(filePath)); 这个代码,首先创建一个 FileInputStream 的对象,然后再传入到 BufferedInputStream 中,这是要干什么,为什么要这么做。现在

不更新了 3488

Win10或Win8下ObjectARX2015 Wizard向导创建项目失败解决方法

[原创]objectARX 2015 Wizard安装向导在Win8/win10下无法创建项目的解决方法总结 by edata @2017-5-1 objectARX 2015 Wizard安装向导在Win8/win10下无法创建项目的解决方法 因为Win8/Win10对系统盘(默认c:)使用了高级权限管理,所以在此盘下操作文件的修改工作都需要管理员权限才行。 基于这个原因,导致非管理员安

edata的博客 7029

ADS 使用调整器动态调参教程(Tuning)

ADS动态调参教程

weixin_42845306的博客 1万+

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

一、什么是装饰者模式 装饰着模式:简单的一句话理解就是,动态的给一个对象添加一些额外的功能,装饰者模式相对于生成子类更加的灵活。 我们来看下装饰者模式的UML图: 装饰模式,是面向对象编程领域中,一种动态地往一个类中添加新的行为的设计模式。就功能而言,装饰模式相比生成子类更为灵活,这样可以给某个对象而不是整个类添加一些功能。 意图:动态地给一个对象添加一些额外的职责和增加功能。 主要解决:一般的...

qq_43170213的博客 374

若依ruoyi框架实现单点登录或者接入统一认证

log.info("单点登录用户[{}]不存在, 需要创建.", loginName);log.info("单点登录用户[{}]已存在.", loginName);jsonObjectData.put("nickName","单点1");if (code.equals("0")) {//验证成功需要自动登录。jsonObject.put("msg","验证成功");ajax.put("msg", "登录成功");

GitHub质检员 2万+

装饰(Decorator)模式

1、装饰(Decorator)模式 动态给一个对象添加一些额外的职责。就增加功能来说,装饰模式比生成子类更为灵活。Component是定义一个对象接口、可以给这些对象动态地添加职责。ConcreteComponent是定义了一个具体的对象,也可以给这个对象添加一些职责。Decorator,装饰抽象类,继承了Component,从外类来扩展Component类的功能,但对于Component来...

weixin_30918415的博客 191

通达信量化打板选股指标公式源码副图

X_2:=3*LOW;X_13:=4;X_14:=3;X_15:=2;X_16:=1;

gpzb7的博客 4484

NVIDIA Cosmos:生成式物理世界模型 从入门到精通1

Prompt Upsampler模型通过微调T5-XXL实现低质量描述到专业级描述的自动扩展,将"一个机器人在仓库"转换为"一台橙色的Kiva自主移动机器人在现代化电商仓库的过道中行驶,头顶的LED阵列投射出冷白色光线,地面反射出机器人的轮廓,摄像机以1.5米高度跟随拍摄,轻微晃动模拟手持效果"。控制输入(深度图、语义分割等)经独立的卷积编码器处理后注入控制分支,提取的多尺度特征通过零卷积层(zero convolution)逐步释放至主网络,避免初始训练阶段的噪声干扰。视频条件通过时序掩码控制扩散范围。

VectorShift的博客 137

Java添加新代码_关于java:decorator设计模式,用于向现有对象添加新方法和代码...

我是设计模式的新手。 我正在尝试使用装饰器设计模式向现有应用添加新代码和功能。假设我有一类App,其中有两个方法" Add"和" Multiply"。 在某个时间点(运行时),应用程序还将需要计算平均值。因此,我正在尝试使用装饰器设计模式来实现这一点。到目前为止,我有:public class App implements Code{public int a=2;public int b=3;@O...

weixin_33705384的博客 319

Pulseaudio之同步/异步(十一)

PulseAudio是一个声音服务器,一个后台进程从一个或多个音源(进程或输入设备)接受声音输入 然后重定向声音到一个或多个槽(声卡,远程网络PulseAudio服务,或其他进程)。 PulseAudio的主要特点包括: 可对每一个应用程序进行音量控制Per-application volume controls 可扩展的插件与支持可装载模块架构 兼容性许多流行的音频应用程序 支持多重音源和多重输出 低延时操作和支持延迟测量 一个对处理器资源效率零拷贝内存架构 能够发现本地网络上使用PulseAu

Android系统攻城狮 999

装饰模式(Decorator模式)详解

在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等。在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成了一些核心功能。但在不改变其结构的情况下,可以动态地扩展其功能。所有这些都可以釆用装饰模式来实现。 1.装饰模式的定义与特点 装饰(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式...

傅红雪的专栏 6021

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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

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

ProgramNovice的博客 1782

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

装饰器模式(Decorator Pattern)模式

装饰器模式是一种结构型设计模式,它允许你通过将对象放入包含行为的特殊封装对象中来为原对象添加新的行为。装饰器模式遵循开闭原则,允许在不修改现有对象结构的情况下向其添加新功能。装饰器模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式比生成子类更为灵活。装饰器模式是一种强大而灵活的结构型设计模式,它允许通过将对象包装在装饰器类的对象中来动态地向对象添加功能,而无需修改原始对象的代码。优点符合开闭原则,易于扩展比继承更灵活,避免类爆炸问题可以动态组合功能。

yk_dflkg的博客 1188

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

装饰(Decorator)模式是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构

装饰模式是实现开闭原则(对扩展开放,对修改封闭)的一个典型例子,它允许你通过添加新的装饰类来扩展系统的功能,而不需要修改现有的代码。

[Blog][Domain] programb.blog.youkuaiyun.com 1001

我的java设计模式 总结【5】装饰器 Decorator

文章目录装饰器模式 Decorator特点举例JDK中的 Decorator 装饰器模式 Decorator 特点 Decorator 设计模式不会改变原有的东西,只是增加新的外观或者功能,样式等,且随着时间的推移,可以不断的实施修饰操作。在面向对象的程序设计中,扩展系统的原有功能也可以采用继承、组合的方式。继承也不会改变原有类(父类),但是由于工程的复杂和很多不可预测的改变,比如不同业务的数据组合数量简直无法想想,难道我们要为每一种组合都定义一个子类吗?显然这是不现实的,即通过继承的方式来应对未来的功能和

学海拾遗 1716

设计模式学习(十二):Decorator装饰器模式

假如现在有一块蛋糕,如果只涂上奶油,其他什么都不加,就是奶油蛋糕。如果加上草莓,就是草莓奶油蛋糕。如果再加上一块黑色巧克力板,上面用白色巧克力写上姓名,然后插上代表年龄的蜡烛,就变成了一块生日蛋糕。不论是蛋糕、奶油蛋糕、草莓蛋糕还是生日蛋糕,它们的核心都是蛋糕。不过,经过涂上奶油,加上草莓等装饰后,蛋糕的味道变得更加甜美了,目的也变得更加明确了。程序中的对象与蛋糕十分相似。首先有一个相当于蛋糕的对象,然后像不断地装饰蛋糕一样地不断地对其增加功能,它就变成了使用目的更加明确的对象。

m0_49499183的博客 2492

如何彻底搞懂装饰器(Decorator)设计模式?

实现装饰器模式的前提是我们需要采用面向接口的编程模式,然后对功能的类型和职责进行合理的划分,确保不同的装饰器类能够独立承接不同的业务功能。因为这里实现的是一个先进先出的策略,所有,我们通过使用一个Deque对象来达到这种效果,这也让我们间接掌握了实现FIFO机制的一种实现方案。可以看到,整个PerpetualCache类的代码结构非常明确,除了一个id属性之外,代表缓存的cache属性只是一个HashMap,是一种典型的基于内存的缓存实现方案。现在,新需求来了,我们需要在绘制形状的基础上对该形状添加边框。

2401_83062316的博客 1797

「软件设计模式」装饰者模式(Decorator)

装饰者模式(Decorator Pattern)是一种结构型设计模式,它通过将对象放入包含行为的特殊封装对象中,动态地为原始对象添加新功能,比继承更灵活。装饰者模式通过灵活的对象组合代替僵化的类继承,为系统扩展提供了优雅的解决方案。使用unique_ptr管理组件生命周期通过抽象类保证接口一致性利用现代C++特性简化实现当面对需要动态扩展功能的场景时,装饰者模式就像编程世界的"俄罗斯套娃",让每个装饰器层层包裹核心组件,最终组合出强大的功能集合。

ThereIsNoCode 1090

装饰者模式 Decorator Pattern

作用:动态地给一个对象添加一些额外的职责。就增加功能来说, Decorator模式相比生成子类更为灵活。装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任。 装饰模式的优点: (1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统...

.... 永远年轻,永远热泪盈眶 1万+

设计模式之: Decorator(装饰器)模式

通过一个简单的列子来说明什么是"Decorator"模式,及其优点

不积跬步,无以至千里;不积小流,无以成江海! 2229

深入解析 C# 中的装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,它允许我们通过将一个对象包裹在另一个对象中,动态地增加额外的功能。与继承不同,装饰器模式通过组合而非继承来扩展对象的功能。这种方式具有更高的灵活性,且不破坏原始对象的结构。通过将对象包装在装饰器类中,可以在运行时增加或改变对象的功能,而无需改变原始类的代码。首先,定义一个通用的接口ICar,它声明了所有车类需要实现的方法。装饰器模式提供了一种灵活的方式来扩展对象的功能,而无需修改其原始代码。通过组合不同的装饰器,我们可以动态地为对象添加新的职责,从而避免继承带来的复杂性。

net core ,前端 ,python 全栈开发 1298

装饰器模式(Decorator Pattern)

动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。一般的,我们为了扩展一个类经常使用继承方式实现,由于继承为类引入静态特征,并且随着扩展功能的增多,子类会很膨胀。在不想增加很多子类的情况下扩展类。装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。多层装饰比较复杂。1、扩展一个类的功能。2、动态增加功能,动态撤销。可代替继承。

u013115157的博客 575

设计模式【8】——装饰器模式(Decorator 模式)

在系统程序设计与开发过程中,会经常遇到需要为一个已经定义好的类添加新的功能或者操作,通常的情况下我们可以定义一个新类继承自定义好的类。但是这样会带来一个问题:当具体子类要添加新的功能函数时,就必须向其父类添加一个相应的功能函数的抽象接口,否则无法通过父类指针实现调用功能。因此,处于高层的父类就承载了太多的抽象接口,而且所有继承自父类的子类都不可避免继承了这些接口,但是部分功能可能并不是该子类所需要的。另一方面,通过继承的方式解决的话还增加了系统的复杂性。

sinat_42974726的博客 588
上一篇: java.net.BindException: Address already in use: JVM_Bind:8080
下一篇: 自己玩的DEMO级项目压力测试,网络先挂。
NationSoftware
博客等级 码龄18年 2粉丝 30原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值