八:装饰模式
装饰
(Decorator)
模式
又叫包装
(Wrapper)
模式
,它以对客户端透明的方式动态地扩展对象的功能,可以在不使用创造更多子类的情况下,将对象的功能加以扩展,是继承关系的一种替代。装饰模式使用原来被装饰类的一个子类的实例,把客户端的调用委派到被装饰类,其扩展是完全透明的。
涉及角色:
抽象构件
(Component)
角色:一个接口或者是抽象类,规范被装饰类,就是我们最核心、最原始的对象。在装饰模式中必然有一个被提取出来的最核心、最原始、最基本的接口或抽象类
具体构件
(Component)
角色:一个实现,被装饰的就是此角色
装饰
(Decorator)
角色:一般是抽象类,持有一个
Component
对象的实例
具体装饰
(ConcreteDecorator)
角色:具体的装饰类,既需要给被装饰类扩展什么功能。
再次说明,装饰模式是对继承的补充,继承不利于易维护、易扩展和易复用等的特性。继承是静态的给类增加功能,而装饰模式是动态的。
下面以一个例子来说明:
场景:大二的时候,学院坑人的要在暑假期间把每个人的历年成绩单寄给家长,并要家长签字后等假期结束上交
package com.co.patterns.decorator;
/**
* 成绩单
*/
public abstract class GradeReport {
// 展示成绩
public abstract void report();
// 家长签字
public abstract void sign(String name);
}
package com.co.patterns.decorator;
/**
* 我的成绩单
*/
public class SchoolGradeReport extends GradeReport {
public void report() {
System.out.println("尊敬的XXX家长:");
System.out.println(" ......");
System.out.println(" 高数 62 英语65 体育 98 电路 63");
System.out.println(" .......");
System.out.println(" 家长签名: ");
}
public void sign(String name) {
System.out.println("家长的名字:" + name);
}
}
package com.co.patterns.decorator;
/**
* 家长看了成绩单,并准备签字
*/
public class Client {
public static void main(String[] args) {
GradeReport report = new SchoolGradeReport();
// 看成绩单
report.report();
// 那么低的分数还有脸签字!
}
}
以上就是原始成绩单的样子以及客户端。但是我想,我要对成绩单装饰一下,然后让家长高兴的签字,我需要这样:
首先告诉家长,我们班里各科最高分:高数72 英语73 体育98 电路79;然后说我们班里总共就50个人,我之前是40几名,现在是20几名了(实际上有十几个人考试闹肚子了)。
我们用继承的方式,给成绩单增加一个子类,包装后:
package com.co.patterns.decorator;
/**
* 包装的成绩单
*/
public class NiceSchoolGradeReport extends SchoolGradeReport {
// 首先要定义你要美化的方法,先给老爸说学校最高成绩
private void reportHighScore() {
System.out.println("这次考试高数最高分是 72 英语73 体育 98 电路 78");
}
// 看完毕成绩单后,我再汇报排名情况
private void reportSort() {
System.out.println("我是排名第22名...");
}
// 由于汇报的内容已经发生变更,那所以要重写父类
public void report() {
this.reportHighScore(); // 先说最高成绩
super.report(); // 然后家长看成绩单
this.reportSort(); // 然后告诉家长学习学校排名
}
}
//美化过的成绩单拿过来
GradeReport report= new NiceSchoolGradeReport();
report.report();
report.sign("家长XXX");
但是现实情况是复杂的,假如家长看了最高成绩和我的成绩之后很高兴,不看排名了就直接签字或者是先看排名情况....,这时候该怎么办?再写子类?这样类就会激增,后期不好维护,还有设计时如果继承超过两层就可不太好了!装饰模式
就解决了这个问题。
package com.co.patterns.decorator;
/**
* 装饰角色
*/
public class Decorator extends GradeReport {
// 首先我要知道是那个成绩单
private GradeReport sr;
// 构造函数,传递成绩单过来
public Decorator(GradeReport sr) {
this.sr = sr;
}
// 成绩单还是要被看到的
public void report() {
this.sr.report();
}
// 看完毕还是要签名的
public void sign(String name) {
this.sr.sign(name);
}
}
package com.co.patterns.decorator;
/**
* 具体装饰角色
*/
public class HighScoreDecorator extends Decorator {
// 构造函数
public HighScoreDecorator(GradeReport sr) {
super(sr);
}
// 我要汇报最高成绩
private void reportHighScore() {
System.out.println("这次考试高数最高分是 72 英语73 体育 98 电路 78");
}
// 最高成绩在看成绩单前告诉他
public void report() {
this.reportHighScore();
super.report();
}
}
package com.co.patterns.decorator;
public class SortDecorator extends Decorator {
// 构造函数
public SortDecorator(GradeReport sr) {
super(sr);
}
// 告诉老爸学校的排名情况
private void reportSort() {
System.out.println("我的排名是22");
}
// 看完成绩单后再告诉他
public void report() {
super.report();
this.reportSort();
}
}
package com.co.patterns.decorator;
public class ClientWrapper {
public static void main(String[] args) {
//成绩单拿过来
GradeReport sr;
sr = new SchoolGradeReport(); //原装的成绩单
//加了最高分说明的成绩单
sr = new HighScoreDecorator(sr);
//又加了成绩排名的说明
sr = new SortDecorator(sr);
//看成绩单
sr.report();
System.out.println();
//一看,很开心,就签名了
sr.sign("家长XXX");
}
}
输出结果就这样了:
![]()
装饰模式的类图:
![]()
<!-- [if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]-->
<!-- [if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="156">
</w:LatentStyles>
</xml><![endif]--><!-- [if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
</style>
<![endif]-->
应用场景:
(1)
需要扩展一个类得功能
(2)
动态地给一个对象增加功能,这些功能可以再动态地撤销
(3)
需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使得继承关系变得不现实
由于装饰模式的灵活性,也意味着比继承更容易出错,比如说,不同的装饰类在排列组合时可能会产生一些不合理的组合等;还会长生比继承更多的对象。
同样的,也可以进行简化:如果只有一个具体构件角色而没有抽象构件角色,那么装饰类可以是具体构件角色的一个子类;如果只有一个具体装饰角色,则可以把装饰角色和具体装饰角色合并成一个。
分享到:
相关推荐
marlett_01_0109
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
stassar_3cd_01_0716
malpass_02_0907
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
matsumoto_01_1107
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
代码
大模型创业者手册-法务与产品合规篇.pdf
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
指标体系数据开发
半导体三极管β值测量仪的设计与制作
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!
本文将带你深入了解如何使用OpenCV库实现图片拼接技术,打造令人惊叹的全景图像。通过清晰的步骤讲解和代码示例
nicholl_01_0508
lim_3ck_04_0719
DeepSeek入门宝典-个人使用篇.pdf