装饰器模式在Java集合框架中最典型落地是Collections同步包装器,如synchronizedList——它不修改原始容器,而是通过包装赋予线程安全能力,内部持原始引用并转发调用,仅在方法入口出口加synchronized块。

装饰器模式在 Java 集合框架中最典型、最实用的落地,就是 Collections 工具类提供的同步包装器(如 synchronizedList、synchronizedSet)——它们不修改原始容器,而是通过“包装”赋予其线程安全能力。
同步包装的本质是视图增强,不是复制或改造
调用 Collections.synchronizedList(new ArrayList()) 返回的并不是一个新集合,而是一个 SynchronizedList 实例。它内部只持有一个对原始 ArrayList 的引用,所有方法(如 add()、get()、size())都转发给底层列表执行,但在每个公共方法入口和出口自动加上 synchronized(this) 块。
- 原始
ArrayList本身完全没变,仍可被其他引用直接操作(可能引发竞态); -
SynchronizedList提供的是一个“带锁的访问通道”,仅约束经由它调用的行为; - 它没有重写
iterator()的线程安全性——返回的迭代器仍需手动同步,这是文档明确提醒的关键限制。
多层装饰支持运行时灵活组合
装饰器天然支持嵌套,比如你既需要只读语义,又需要线程安全:
-
Collections.synchronizedList(Collections.unmodifiableList(list))是合法且常见的写法; - 外层
synchronizedList保证并发调用安全,内层unmodifiableList拦截所有修改操作; - 执行顺序是从外向内:先加锁 → 再判断是否允许修改 → 最后调用原始方法;
- 这种组合不依赖编译期继承关系,完全在运行时构建,避免了为每种组合预定义子类。
与继承和代理的关键区别
它不是继承(没扩展现有类),也不是通用代理(不拦截所有访问、不处理反射或私有字段)。它的设计非常克制:
- 只增强接口契约中声明的方法,不暴露底层实现细节;
- 不改变对象身份(
==判断仍指向原始容器); - 不引入额外状态,只添加行为控制逻辑(锁、校验、日志等);
- 符合开闭原则:新增一种增强(如加监控埋点),只需新增一个装饰器类,不影响已有代码。
使用时必须注意的陷阱
同步包装器容易误用,常见问题包括:
- 误以为整个集合已“全局线程安全”——实际仅单个方法原子,复合操作(如
if (!list.contains(x)) list.add(x))仍需外部同步; - 忽略迭代器非线程安全——必须用
synchronized(list) { ... list.iterator() ... }包裹; - 将包装后的引用和原始引用混用,导致部分操作绕过同步逻辑;
- 在高并发场景下,粗粒度锁(
synchronized(this))可能成为性能瓶颈,此时应考虑CopyOnWriteArrayList或ConcurrentHashMap等专用并发集合。

















