设计模式-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 类似对象的外壳,通过一层层的嵌套,动态地给对象添加功能。

相关推荐
计算机毕设匠心工作室1 小时前
【python大数据毕设实战】全面皮肤病症状数据可视化分析系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习、实战教学
后端·python·mysql
摆烂工程师1 小时前
2025年12月最新的 Google AI One Pro 1年会员教育认证通关指南
前端·后端·ai编程
qq_12498707532 小时前
基于SpringBoot+vue的小黄蜂外卖平台(源码+论文+部署+安装)
java·开发语言·vue.js·spring boot·后端·mysql·毕业设计
代码与野兽2 小时前
AI交易,怎么让LLM自己挑选数据源?
前端·javascript·后端
天天摸鱼的java工程师2 小时前
JDK 25 到底更新了什么?这篇全景式解读带你全面掌握
java·后端
非鱼feiyu2 小时前
自关联数据表查询优化实践:以 Django + 递归 CTE 构建树结构为例
数据库·后端·django
零日失眠者2 小时前
这5个Python库一旦掌握就离不开
后端·python
幌才_loong2 小时前
.NET8 × Redis 实战宝典:从配置到落地,搞定高并发缓存就这篇!
后端·.net
用户8356290780512 小时前
如何使用 Python 从 Word 文档中批量提取表格数据
后端·python
l***37093 小时前
spring 跨域CORS Filter
java·后端·spring