三分钟理解“装饰模式”——设计模式轻松掌握

什么是装饰模式?

在运行的过程中,给一个对象动态地添加一些额外的行为。每一个具体的装饰类都为被装饰类添加一个功能。

装饰模式的类图

1.需要被装饰的对象所在的类和装饰类都有一个共同的父类Component,该类中拥有需要添加额外功能的函数:operation();

class ConcreteComponent() extends Component{
	public void operation(){
		//本函数原本就要做的事情
	}
}

2.ConcreteComponent是需要被装饰的类;Decorator是装饰类。

3.Decorator类中持有被装饰对象的引用,客户端通过setComponent(Component)设置;

4.Decorator类的operation()函数中,执行了被用户set进去的component对象中的operation()函数,也就是首先执行被装饰类原本的功能;

class Decorator() extends Component{//需要被装饰的对象private Component component;//提供给客户端将需要被装饰的对象设置进来public void setComponent(Component component){this.component = component;}//执行需要被装饰对象原本的operation函数public void operation(){this.component.operation();}}

Decorator的子类们的operation()函数,拥有被装饰类原本的功能和新需要增加的功能。

class ConcreteDecorator() extends Decorator{
	//需要被装饰的对象
	private Component component;

	//提供给客户端将需要被装饰的对象设置进来
	public void setComponent(Component component){
		this.component = component;
	}

	//执行需要被装饰对象原本的operation函数+附加的功能
	public void operation(){
		//新的功能……………………
		super.operation();
		//新的功能……………………
	}
}

客户端代码:

public static void main(String[] args) {
	//创建一个需要被装饰的对象
	ConcreteComponent concreteComponent = new ConcreteComponent();

	//创建一系列修饰类的对象
	Decorator decoratorA = new ConcreteDecoratorA();
	Decorator decoratorB = new ConcreteDecoratorB();

	//先使用ConcreteDecoratorA包装被装饰对象
	decoratorA.setComponent(concreteComponent);
	//再使用ConcreteDecoratorB包装decoratorA对象
	decoratorB.setComponent(decoratorA);
}

此时,decoratorB对象就是原本需要被装饰的concreteComponent对象,只不过这个对象的operation()函数在原本operation()的基础上增加了ConcreteDecoratorA和ConcreteDecoratorB新的功能。

装饰模式和建造者模式的异同?

相同点:建造者模式和装饰模式都使用了面向切面编程的思想,装饰模式中的装饰类和建造者模式中建造者类的一个个函数都是为被装饰对象附加函数额外功能或为对象中的属性赋值。

不同点:建造者给对象添砖加瓦的顺序是固定的,在Director类中写好的;

而装饰模式中需要添加哪些操作是由客户端决定的。

建造者模式的详细介绍请移步至:http://blog.csdn.net/u010425776/article/details/48104143

装饰模式的优点

装饰模式是为已有的功能动态添加更多功能的一种方式。

以往在设计程序的过程中,当系统需要新功能时,就在旧的类中添加新的代码。

但这种方式的问题在于,如果它们在类中添加了新的方法、新的字段、新的逻辑,就会增加主类的复杂度,而这些新加入的东西仅仅是为了满足一些只在某种特定情况下才回执行的特殊行为的需要。

而装饰模式提供了一种非常好的解决方案,

它把每一个要额外添加的功能单独封装在一个个类中,并让这个类包装它所要装饰的对象。

因此,当一个类需要执行特殊行为时,客户端就可以在运行时有选择地添加所需要的附加功能。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

比较一下以“反射”和“表达式”执行方法的性能差异

由于频繁地使用反射会影响性能,所以ASP.NET MVC采用了表达式树的方式来执行目标Action方法。具体来说,ASP.NET MVC会构建一个表达式来体现针...

1717
来自专栏恰同学骚年

.NET基础拾遗(2)面向对象的实现和异常的处理基础

  在C#中申明一个类型时,只支持单继承(即继承一个父类),但支持实现多个接口(Java也是如此)。像C++可能会支持同时继承自多个父类,但.NET的设计小组认...

551
来自专栏Golang语言社区

golang(Go语言) byte/[]byte 与 二进制形式字符串 互转

效果 把某个字节或字节数组转换成字符串01的形式,一个字节用8个”0”或”1”字符表示。比如: byte(3) –> “00000011” []byte{1...

3617
来自专栏技术博客

C# 委托一(委托基础)

委托可以这样来理解:它是一种数据类型,和引用类型类似,不过和一般的类相比,委托的实例不是在堆中的数据,而是一个方法。委托类似于引用类型,和C++中的函数指针很相...

584
来自专栏偏前端工程师的驿站

委托与事件

  首先多谢网上的大牛们无私地分享自己的经验,让我这样的小鸟能站在巨人的肩膀上不断前进!   参考网址:http://www.knowsky.com/39593...

1696
来自专栏java一日一条

Java 编程要点之 I/O 流详解

字节流处理原始的二进制数据 I/O。输入输出的是8位字节,相关的类为 InputStream 和 OutputStream.

622
来自专栏恰同学骚年

C#基础与常用数据结构学习笔记

  接口相当于没有方法实现的抽象类,接口方法不要加各种访问级别:例如public,private等。

813
来自专栏NetCore

.NET反射、委托技术与设计模式

1 反射技术与设计模式   反射(Reflection)是。NET中的重要机制,通过放射,可以在运行时获得。NET中每一个类型(包括类、结构、委托、接口和枚举...

1959
来自专栏lulianqi

理解委托类型

delegate 是一种可用于封装命名或匿名方法的引用类型。(并不是所有的引用类型都是class)

540
来自专栏遊俠扎彪

C语言C99标准中的变长数组(VLA)

长期以来,我都很自然的认为定义和声明数组时,数组大小必须是一个常量表达式,因为刚学编程的时候在这个上面翻过好多次语法错误。那个时候大致会写如下的代码:

2389

扫码关注云+社区