概述和作用
装饰器模式是一种结构型设计模式,允许在运行时动态地给对象添加额外的功能或职责。它通过创建装饰器类来包装原始对象,从而在不修改原始类代码的情况下扩展其功能。
装饰器模式适用于以下场景:
需要动态地给对象添加功能或职责,且这些功能或职责可以随时添加和移除。
需要避免通过继承进行功能扩展,因为继承会导致类的层次结构过于复杂。
举例
假设我们有一个图形绘制系统,需要给图形添加不同的装饰效果,如边框、阴影等。我们可以使用装饰器模式来实现。
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 rectangle = new Rectangle();
// 给圆形添加边框
Shape circleWithBorder = new BorderDecorator(circle);
circleWithBorder.draw(); // 输出:绘制圆形 添加边框
// 给矩形添加阴影
Shape rectangleWithShadow = new ShadowDecorator(rectangle);
rectangleWithShadow.draw(); // 输出:绘制矩形 添加阴影
// 给圆形同时添加边框和阴影
Shape circleWithBorderAndShadow = new ShadowDecorator(new BorderDecorator(circle));
circleWithBorderAndShadow.draw(); // 输出:绘制圆形 添加边框 添加阴影
}
}
优点和缺点
优点
**1.动态扩展功能:**可以在运行时动态地给对象添加功能,而无需修改原始类的代码。
**2.代码复用性高:**通过装饰器类的组合,可以灵活地组合不同的功能,避免了类的爆炸性增长。
**3.符合开闭原则:**对扩展开放,对修改封闭。可以在不修改原始类的情况下扩展其功能。
缺点
**1.可能导致设计复杂:**如果过度使用装饰器模式,可能会导致系统设计变得复杂,难以理解。
**2.装饰器组合的复杂性:**如果装饰器之间存在依赖关系,可能会导致装饰器的组合变得复杂。
不使用装饰器模式的实现方式
如果不使用装饰器模式,可以通过继承或组合的方式来实现类似的功能。
继承方式
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("添加阴影");
}
}
然而,这种方式会导致类的爆炸性增长,因为每一种功能组合都需要一个单独的类。而装饰器模式通过装饰器类的组合,可以更灵活地实现功能扩展。