`

设计模式-装饰模式

阅读更多

 

八:装饰模式

      装饰 (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)    需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使得继承关系变得不现实

由于装饰模式的灵活性,也意味着比继承更容易出错,比如说,不同的装饰类在排列组合时可能会产生一些不合理的组合等;还会长生比继承更多的对象。

 

同样的,也可以进行简化:如果只有一个具体构件角色而没有抽象构件角色,那么装饰类可以是具体构件角色的一个子类;如果只有一个具体装饰角色,则可以把装饰角色和具体装饰角色合并成一个。

 

0
2
分享到:
评论

相关推荐

    marlett_01_0109.pdf

    marlett_01_0109

    [AB PLC例程源码][MMS_040384]Winder Application.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    stassar_3cd_01_0716.pdf

    stassar_3cd_01_0716

    malpass_02_0907.pdf

    malpass_02_0907

    [AB PLC例程源码][MMS_046459]InView on EtherNet Add On Instruction.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    matlab程序代码项目案例:matlab程序代码项目案例文档+程序具有输出LC滤波器的三相逆变器的前馈神经网络模型预测控制.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    matlab程序代码项目案例:matlab程序代码项目案例基于运动学车辆模型的开放式驾驶MPC横向控制算法.zip

    matlab程序代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    matsumoto_01_1107.pdf

    matsumoto_01_1107

    [AB PLC例程源码][MMS_045719]Rotary Knife with SoftLogix.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    QT第五课-QT系统相关-文件

    代码

    大模型创业者手册-法务与产品合规篇.pdf

    大模型创业者手册-法务与产品合规篇.pdf

    [AB PLC例程源码][MMS_046456]ME Equipment Status Summary Faceplate for PowerFlex, Kinetix, E3 Plus,.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    指标体系数据开发.pptx

    指标体系数据开发

    半导体三极管β值测量仪的设计与制作

    半导体三极管β值测量仪的设计与制作

    [AB PLC例程源码][MMS_047416]ME Faceplates-AOIs for GuardLogix Safety Systems.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    [AB PLC例程源码][MMS_041473]Input Time Stamping.zip

    AB PLC例程代码项目案例 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我!

    本文将带你深入了解如何使用OpenCV库实现图片拼接技术,打造令人惊叹的全景图像。通过清晰的步骤讲解和代码示例

    本文将带你深入了解如何使用OpenCV库实现图片拼接技术,打造令人惊叹的全景图像。通过清晰的步骤讲解和代码示例

    nicholl_01_0508.pdf

    nicholl_01_0508

    lim_3ck_04_0719.pdf

    lim_3ck_04_0719

    DeepSeek入门宝典-个人使用篇.pdf

    DeepSeek入门宝典-个人使用篇.pdf

Global site tag (gtag.js) - Google Analytics