设计模式-Decorator

组成

结构型模式涉及到如何组合类和对象,以获得更大的结构,更丰富的功能。主要有"类继承、对象组合"两种方式,

装饰器模式(Decorator)可以动态地给对象添加一些额外的功能,比如有时我们希望给某个对象而不是整个类添加一些功能,那么就可以用装饰器模式,把目标对象嵌入到装饰器对象中。

装饰器模式的组成如下:

Component:一个接口对象

ConcreteComponent:Component 的具体实现类

Decorator:装饰器接口,维持一个指向 Component 对象的引用,必须继承自 Component 接口

ConcreteDecorator:装饰器的具体实现类,用于向 Component 对象添加职责

Decorator 将请求转发给它的 Component 对象,并有可能在转发请求前后执行一些附加的动作。

应用场景

1、希望给某个对象增加功能,而不是整个类,不会影响这个类其他对象。

2、继承不利于系统维护,甚至不能使用继承关系的场景。

3、需要动态、透明的给对象添加或撤销功能。

示例代码

Java 类库中 Collections 就有一个很典型的装饰器模式实现:Collecitons.SynchronizedList()。

java 复制代码
List<String> list = Collections.synchronizedList(new ArrayList<>());

该方法可以把非线程安全的 List 对象包装成线程安全的 List 对象返回,很符合"给某个对象增加功能,但不影响整个类"的要求。

改方法的内部实现,是使用一个新的类 SynchronizedList作为装饰器,包装了传入的 List 对象,该类的定义如下:

java 复制代码
static class SynchronizedList<E> extends SynchronizedCollection<E> implements List<E> {
	private static final long serialVersionUID = -7754090372962971524L;

	final List<E> list;

	SynchronizedList(List<E> list) {
		super(list);
		this.list = list;
	}
	SynchronizedList(List<E> list, Object mutex) {
		super(list, mutex);
		this.list = list;
	}

	
	public E get(int index) {
		synchronized (mutex) {return list.get(index);}
	}
}

可以看到,这个装饰器类自身也继承了它要装饰的 Component (List 接口),并实现了 List 的方法,在调用时,会使用 synchroinzed 加锁,在转发给被装饰的对象 list,让 list 的方法变得线程安全。

优点和缺点

优点

1、比继承更加灵活

使用装饰器可以在需要的时候给某个对象增加功能,而不是使用继承,让所有子类对象都被增强。

2、简单、即用即付

不需要在一个装饰器类中定义所有需要增强的功能,而是可以定义多个简单的装饰器类,逐个调用,逐渐给 component 添加功能,从简单的部件组合出复杂的功能。

缺点

1、Decorator 和 Compnent 不一样

虽然 Decorator 继承了 Compnent 接口,但实际上同名方法和 Compnent 还是有差异的,不能把 Decorator 当做 Compnent 使用。

2、会产生很多装饰器类

如果要添加的功能很多,会创建很多相似的装饰器类和对象,使的维护和排查更加困难。

小结

装饰器模式可以在不改变 Compnent 实现的前提下,给 Compnent 对象增加功能,并且可以保持 Compnent 的简单性。

Decorator 类似对象的外壳,通过一层层的嵌套,动态地给对象添加功能。

相关推荐
Overboom3 小时前
[C++] --- 常用设计模式
开发语言·c++·设计模式
你的人类朋友4 小时前
【Node】认识一下Node.js 中的 VM 模块
前端·后端·node.js
weixin_419658315 小时前
Spring 的统一功能
java·后端·spring
小许学java5 小时前
Spring AI-流式编程
java·后端·spring·sse·spring ai
canonical_entropy5 小时前
对《DDD本质论》一文的解读
后端·架构·领域驱动设计
码事漫谈6 小时前
我用亲身经历告诉你,为什么程序员千万别不把英语当回事
后端
码事漫谈6 小时前
C++ const 用法全面总结与深度解析
后端
间彧6 小时前
分布式单例模式在微服务架构中的实际应用案例
后端
间彧6 小时前
分布式系统中保证单例唯一性的Java解决方案
后端
间彧6 小时前
为什么避免在单例中保存上下文状态
后端