# 装饰器模式
# 概念
装饰器模式(Decorator Pattern)是一种结构型设计模式,核心思想是通过创建装饰器类来包装原始对象,在运行时动态地为其添加额外功能或职责,而无需修改原始类的代码。其本质是对继承关系的一种替代方案,通过组合而非继承实现功能的扩展。
# 作用
1.动态扩展功能:支持在运行时为对象动态添加或移除功能,满足灵活多变的需求。
2.避免类爆炸:通过装饰器类的组合实现功能扩展,替代继承导致的子类数量指数级增长问题。
3.符合开闭原则:对扩展开放(新增装饰器类即可扩展功能),对修改封闭(无需修改原始类代码)。
4.解耦功能与对象:将功能实现与对象本身分离,提高代码的可维护性和复用性。
# 场景
1.需要动态添加/移除功能:如图形绘制系统中,用户可自由选择是否添加边框、阴影等效果。
2.避免继承层次过深:当功能扩展通过继承会导致类结构复杂时(如多个独立功能需要叠加)。
3.功能组合灵活:需要组合多种独立功能时(如同时添加边框和阴影)。
4.运行时功能切换:允许在运行时动态决定是否启用某些功能。
# 举例
以下是一个图形绘制系统中使用装饰器模式的Java代码示例,实现为形状动态添加边框和阴影功能:
// 图形接口
public interface Shape {
void draw();
}
// 圆形实现
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("绘制圆形");
}
}
// 矩形实现
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("绘制矩形");
}
}
// 装饰器基类
public abstract class ShapeDecorator implements Shape {
protected Shape decoratedShape;
public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}
@Override
public void draw() {
decoratedShape.draw();
}
}
// 边框装饰器
public class BorderDecorator extends ShapeDecorator {
public BorderDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
super.draw();
addBorder();
}
private void addBorder() {
System.out.println("添加边框");
}
}
// 阴影装饰器
public class ShadowDecorator extends ShapeDecorator {
public ShadowDecorator(Shape decoratedShape) {
super(decoratedShape);
}
@Override
public void draw() {
super.draw();
addShadow();
}
private void addShadow() {
System.out.println("添加阴影");
}
}
控制台输出:
public class Main {
public static void main(String[] args) {
// 圆形添加边框
Shape circle = new Circle();
Shape circleWithBorder = new BorderDecorator(circle);
circleWithBorder.draw(); // 输出:绘制圆形 添加边框
// 矩形添加阴影
Shape rectangle = new Rectangle();
Shape rectangleWithShadow = new ShadowDecorator(rectangle);
rectangleWithShadow.draw(); // 输出:绘制矩形 添加阴影
// 圆形同时添加边框和阴影
Shape circleWithBoth = new ShadowDecorator(new BorderDecorator(circle));
circleWithBoth.draw(); // 输出:绘制圆形 添加边框 添加阴影
}
}
# 反例
若不使用装饰器模式,通常需要通过继承或组合实现功能扩展,但会导致类数量爆炸或代码冗余:
# 继承方式
// 圆形添加边框
public class CircleWithBorder extends Circle {
@Override
public void draw() {
super.draw();
System.out.println("添加边框");
}
}
// 圆形添加阴影
public class CircleWithShadow extends Circle {
@Override
public void draw() {
super.draw();
System.out.println("添加阴影");
}
}
// 圆形同时添加边框和阴影(需单独定义)
public class CircleWithBorderAndShadow extends Circle {
@Override
public void draw() {
super.draw();
System.out.println("添加边框");
System.out.println("添加阴影");
}
}
# 组合方式
// 圆形添加边框(组合)
public class CircleWithBorder {
private Circle circle;
public CircleWithBorder(Circle circle) {
this.circle = circle;
}
public void draw() {
circle.draw();
System.out.println("添加边框");
}
}
// 圆形添加阴影(组合)
public class CircleWithShadow {
private Circle circle;
public CircleWithShadow(Circle circle) {
this.circle = circle;
}
public void draw() {
circle.draw();
System.out.println("添加阴影");
}
}
问题
1.继承方式中,每增加一种功能组合(如边框+阴影)需定义新类,导致类数量呈指数级增长(N功能×M对象 → N×M类)。
2.组合方式虽避免继承缺陷,但需为每种功能单独定义包装类,代码冗余且灵活性差。
# 原理
# 工作机制
装饰器模式通过递归包装实现功能扩展:
1.定义统一接口(如Shape
),所有对象和装饰器均实现该接口。
2.装饰器基类(如ShapeDecorator
)持有被包装对象,并委托其执行基础功能。
3.具体装饰器(如BorderDecorator
)覆盖接口方法,在调用基础功能后追加新功能(如添加边框)。
4.多层装饰器可嵌套使用(如ShadowDecorator(BorderDecorator(Circle))
),实现功能叠加。
# 缺点
1.设计复杂度增加:过度使用可能导致装饰器链过长,难以追踪执行流程。
2.装饰器依赖关系:若装饰器间存在执行顺序依赖(如边框必须在阴影前添加),需额外逻辑处理。
3.类型暴露风险:客户端可能依赖具体装饰器类型,违背面向接口编程原则。
总结
装饰器模式通过动态包装对象实现功能的灵活扩展,避免了继承导致的类爆炸问题,符合开闭原则。其核心在于将功能作为独立模块,通过组合方式叠加到对象上。适用于需要动态调整功能或避免复杂继承结构的场景,但需注意装饰器链的管理和依赖关系处理。

微信公众号

QQ交流群
如若发现错误,诚心感谢反馈。
愿你倾心相念,愿你学有所成。
愿你朝华相顾,愿你前程似锦。