`

设计模式-装饰模式

阅读更多

 

八:装饰模式

      装饰 (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
分享到:
评论

相关推荐

    设计模式 - 装饰模式(C++实例)

    装饰模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式在软件工程中非常常见,因为它提供了灵活性,使得我们可以独立于对象的组合来扩展功能。 在C++中,装饰...

    JAVA-设计模式-结构型模式-装饰模式

    JAVA-设计模式-结构型模式-装饰模式

    c++设计模式-结构型模式-装饰器模式

    c++设计模式-结构型模式-装饰器模式;QT工程;c++简单源码; 装饰器(Decorator)模式的定义:指在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)的模式,它属于对象结构型模式。

    通过C#实现设计模式-装饰模式(DecoratorPattern).rar

    装饰模式(Decorator Pattern)是一种结构型设计模式,它允许你向一个现有的对象添加新的功能,同时又不改变其结构。装饰模式通过创建一个装饰类,该类包装了原始类的实例,并在调用原始类方法之前或之后添加额外的...

    设计模式--装饰者模式java例子

    装饰者模式是软件设计模式中的一种结构型模式,它的主要目的是动态地给对象添加新的功能,而无需修改原有代码。在Java中,装饰者模式通常通过继承和组合来实现,它提供了一种比继承更灵活的方式来扩展对象的功能。...

    吉林大学设计模式-装饰模式练习

    2.开发一个系统帮助业务部门实现灵活的奖金计算。对于普通员工,主要有个人当月业务奖金、个人当月回款奖金等,对于部门经理,除了有普通员工的奖金外,还有...请写出你所选择的设计模式,画出类图,并给出核心代码。

    C++设计模式--基于Qt4开源跨平台开发框架

    《C++设计模式--基于Qt4开源跨平台开发框架》一书主要探讨了如何在C++编程中利用设计模式,并结合Qt4框架进行高效的跨平台应用开发。设计模式是软件工程中的重要概念,它们是经过时间和实践验证的解决特定问题的模板...

    java常用设计模式-装饰器模式

    Java 设计模式 - 装饰器模式 装饰器模式(Decorator Pattern)是一种结构性设计模式,它允许您在不影响同一类的其他对象的行为的情况下,静态或动态地向单个对象添加行为。该模式非常有用,当您想要在运行时添加或...

    设计模式 - 装饰者模式.rar

    装饰者模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象本身。这种模式的核心思想是通过将对象包装在一个装饰类中来扩展功能,而不是通过继承。以下是对装饰者模式的详细阐述: ...

    设计模式-装饰者模式

    在“设计模式—装饰者模式”中,我们将深入探讨这个模式的概念、实现方式以及实际应用。 装饰者模式的核心概念在于“装饰”(Decorator)和“组件”(Component)。组件是被装饰的基本对象,它可以是接口或者抽象类...

    设计模式-装饰器模式

    装饰器模式是一种结构型设计模式,它允许在不修改对象本身的情况下动态地为对象添加新的行为或职责。这种模式在软件工程中广泛应用,特别是在需要扩展已有功能而不影响原有代码结构时。在iOS开发中,装饰器模式同样...

    23种设计模式--装饰模式

    装饰模式是一种结构型设计模式,它是面向对象设计中用来动态添加或修改对象功能的一种方法。在软件工程中,装饰模式允许我们向一个现有的对象添加新的行为或职责,同时又不改变其原有的结构,从而实现对类的功能扩展...

    设计模式--装饰模式

    装饰模式(Decorator Pattern)是一种结构型设计模式,其主要目的是在不改变对象自身的基础上,在运行时为对象添加新的行为或属性。它通过包装原有对象,而不是通过继承来扩展功能,从而提供了更大的灵活性,避免了...

    设计模式---装饰者模式

    装饰者模式是一种结构型设计模式,它允许在运行时向对象添加新的行为或职责,而无需修改对象的源代码或创建子类。这种模式的核心思想是通过将对象封装在一个装饰器对象内,来扩展对象的功能,同时保持原有接口的不变...

    设计模式-Java语言中的应用

    通过阅读《设计模式-Java语言中的应用》,读者不仅可以掌握设计模式的基本概念和原理,还能学习到如何在实际项目中选择合适的设计模式,以及如何优雅地在Java代码中实现这些模式。这将有助于提升开发者的编程技巧,...

    Java设计模式-装饰者模式

    本章可以称为“给爱用继承的人一个全新的设计眼界”。我们即将再度探讨典型滥用问题。你将在本章学到如何使用对象组合的方式,做到在运行时装饰类。为什么呢?一旦你熟悉了装饰者的技巧...——《Head First 设计模式》

    C++设计模式-基于QT4开源跨平台开发框架 源码

    设计模式分为三大类:创建型模式(如单例、工厂方法、抽象工厂)、结构型模式(如代理、装饰器、适配器)和行为型模式(如观察者、策略、命令)。这些模式都是在特定上下文中解决设计问题的模板,它们可以提高代码的...

    java设计模式---诙谐易懂版

    根据给定文件内容,以下是关于Java设计模式的知识点说明: 1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以...

    cpp代码-设计模式-装饰模式

    装饰模式是一种结构型设计模式,它允许在运行时动态地给对象添加新的行为或职责,同时保持接口的一致性。这种模式在不修改原有对象的基础上,通过包装对象来扩展其功能,提供了比继承更加灵活的扩展机制。 在C++中...

Global site tag (gtag.js) - Google Analytics