设计模式之一致性_Decorator装饰器模式_装饰边框和内容的一致性
一、装饰器模式(Decorator Pattern)
1、模式概述
装饰器模式 是一种 结构型设计模式,它允许 动态地给一个对象添加额外的职责,而不改变其原有结构。装饰器通过 组合 + 委托 的方式,在运行时灵活扩展对象功能。
核心思想:“不改类,只加层 —— 功能层层叠加,行为动态增强。”
装饰器模式 = 接口一致 + 组合增强
- 它不是“硬编码功能”,而是“像搭积木一样动态组装行为”。
2、使用场景
装饰器模式适用于以下情况:
- 需要在 不修改原类代码的前提下,动态地为对象 增加新功能;
- 功能组合 种类繁多,若用继承会导致 类爆炸(如 3 种基础图形 × 4 种边框 × 5 种填充 = 60 个子类);
- 需要 在运行时动态决定对象的行为(如根据用户权限添加日志、加密等);
- 希望 复用功能模块,并能 自由组合(如 I/O 流中的
BufferedInputStream包装FileInputStream)。
典型应用:
- Java I/O 流体系:
BufferedInputStream,DataInputStream等; - Web 开发中的请求/响应包装(如 Spring 的
HttpServletRequestWrapper); - 游戏装备系统(武器 + 火焰附魔 + 暴击附魔);
- UI 控件样式叠加(按钮 + 圆角 + 阴影 + 动画)。
3、示例程序:图形绘制 + 边框装饰
1)抽象构件 Shape
/**
* 抽象构件(Component)
* 定义所有图形的公共行为
*/
public interface Shape {
void draw();
}
2)具体构件(基础图形)
a、圆形
/**
* 具体构件(ConcreteComponent)
*/
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Circle");
}
}
b、矩形
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Shape: Rectangle");
}
}
c、装饰器抽象类 ShapeDecorator
- 构造函数注入被装饰对象;
- 默认行为是 直接委托,子类可 重写以增强。
/**
* 装饰器抽象类(Decorator)
* 持有被装饰对象的引用,并实现相同接口
*/
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
@Override
public void draw() {
decoratedShape.draw(); // 委托给被装饰对象
}
}
4)具体装饰器:红色边框
/**
* 具体装饰器(ConcreteDecorator)
* 为图形添加红色边框
*/
public class RedShapeDecorator extends ShapeDecorator {
public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
// 先绘制原始图形
decoratedShape.draw();
// 再添加装饰行为
setRedBorder();
}
private void setRedBorder() {
System.out.println("Border Color: Red");
}
}
5)客户端测试 Main
-
同一套装饰器可用于 任意图形;
- 新增装饰(如绿色边框、虚线边框)无需修改现有代码;
- 支持 多层嵌套装饰(如红边 + 虚线 + 阴影)。
/**
* 客户端(Client)
* 演示装饰器的动态组合能力
*/
public class Main {
public static void main(String[] args) {
// 1. 原始圆形
Shape circle = new Circle();
System.out.println("=== 普通圆形 ===");
circle.draw();
// 2. 红色边框圆形
Shape redCircle = new RedShapeDecorator(new Circle());
System.out.println("\n=== 红色边框圆形 ===");
redCircle.draw();
// 3. 红色边框矩形
Shape redRectangle = new RedShapeDecorator(new Rectangle());
System.out.println("\n=== 红色边框矩形 ===");
redRectangle.draw();
// 4. 叠加装饰(示例:未来可扩展 GreenBorderDecorator)
// Shape fancyCircle = new GreenBorderDecorator(new RedShapeDecorator(new Circle()));
}
}
输出:
=== 普通圆形 ===
Shape: Circle
=== 红色边框圆形 ===
Shape: Circle
Border Color: Red
=== 红色边框矩形 ===
Shape: Rectangle
Border Color: Red
6)UML 类图
┌──────────────┐
│ Shape │
│--------------│
│ + draw() │
└──────▲───────┘
│
┌───────────────┴───────────────┐
│ │
┌──────▼───────┐ ┌──────────▼────────────┐
│ Circle │ │ ShapeDecorator │
│ Rectangle │ │-----------------------│
└──────────────┘ │ - decoratedShape: Shape│
│-----------------------│
│ + draw() │
└──────────▲────────────┘
│
┌───────────────┴───────────────┐
│ │
┌─────────▼─────────┐ ┌───────────▼────────────┐
│ RedShapeDecorator │ │ GreenBorderDecorator │
│-------------------│ │------------------------│
│ + draw() │ │ + draw() │
└───────────────────┘ └────────────────────────┘
4、FQA
1)与适配器模式的区别
-
适配器是为了“能用”;
-
装饰器是为了“更好用”。
| 模式 | 目的 | 是否改变接口 | 典型用途 |
|---|---|---|---|
| 适配器(Adapter) | 转换接口,使不兼容的类能协同工作 | ✅ 改变(适配成目标接口) | 集成旧系统、第三方库 |
| 装饰器(Decorator) | 增强功能,保持原有接口不变 | ❌ 不改变(完全透明) | 日志、权限、缓存、UI 样式等 |
2)模式优点
-
开闭原则:新增功能只需添加新装饰器,无需修改原有代码;
-
灵活性高:可在运行时动态组合功能;
-
避免类爆炸:相比继承,组合更轻量;
-
单一职责:每个装饰器只负责一个功能。
3)注意事项
- 调试复杂度增加:多层嵌套可能导致调用栈过深;
- 过度设计风险:若功能固定且简单,直接继承更直观;
- 对象类型识别困难:客户端无法直接知道被装饰了多少层(除非暴露内部结构)。


