装饰器模式(Decorator)

为对象动态的添加功能

装饰器模式

简要介绍

就是为了动态的给某个类添加功能

使用场景

不想增加子类的时候,想要扩展某个类的功能,就使用装饰器模式

比如说有一个长方形类,还有一个圆形类,都继承了一个形状接口,现在想给长方形和圆形执行 draw 方法的时候,不单纯是绘制形状,还要加一个红色边框的绘制

一般情况解决:长方形增加一个红色长方形子类,圆形再加一个红色圆形子类,重写 draw 方法

装饰器如何解决:装饰器抽象类实现形状接口,构造方法参数是形状接口,然后一个红色装饰器继承此抽象类,在红色装饰器类中绘制并添加红色边框功能

优点

装饰器和被装饰的类可以独立发展,不耦合,装饰器可以理解为继承的替代,动态扩展某个类功能

缺点

多层装饰会变的复杂

类图

例子

情景描述

比如说有一个长方形类,还有一个圆形类,都继承了一个形状接口,现在想给长方形和圆形执行 draw 方法的时候,不单纯是绘制形状,还要加一个红色边框的绘制

具体实现

shape 形状接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package icu.sunnyc;

/**
* @author :hc
* @date :Created in 2022/4/6 21:46
* @modified
*/
public interface Shape {

/**
* 画图形
*/
void draw();
}

长方形类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package icu.sunnyc;

/**
* @author :hc
* @date :Created in 2022/4/6 21:47
* @modified
*/
public class Rectangle implements Shape {

/**
* 画长方形
*/
@Override
public void draw() {
System.out.println("画一个长方形");
}
}

圆形类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package icu.sunnyc;

/**
* @author :hc
* @date :Created in 2022/4/6 21:48
* @modified
*/
public class Circle implements Shape {

/**
* 画圆
*/
@Override
public void draw() {
System.out.println("画圆");
}
}

装饰器登场:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package icu.sunnyc;

/**
* @author :hc
* @date :Created in 2022/4/6 21:49
* @modified
*/
public abstract class ShapeDecorator implements Shape {

protected Shape decoratedShape;

public ShapeDecorator(Shape decoratedShape) {
this.decoratedShape = decoratedShape;
}

/**
* 画图形
*/
@Override
public void draw() {
decoratedShape.draw();
}
}

红色的装饰器类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package icu.sunnyc;

/**
* @author :hc
* @date :Created in 2022/4/6 21:51
* @modified
*/
public class RedShapeDecorator extends ShapeDecorator {

public RedShapeDecorator(Shape decoratedShape) {
super(decoratedShape);
}

@Override
public void draw() {
decoratedShape.draw();
setRedBorder(decoratedShape);
}

private void setRedBorder(Shape decoratedShape) {
System.out.println("Border Color: Red");
}

}

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package icu.sunnyc;


/**
* @author :hc
* @date :Created in 2022/4/6 21:53
* @modified
*/
public class DecoratorTest {
public static void main(String[] args) {
// 不加装饰的圆
Circle circle = new Circle();
// 加了装饰的圆 有没有一种似曾相识的感觉 new BufferedReader(new FileReader(""))
RedShapeDecorator redCircle = new RedShapeDecorator(new Circle());
// 加了装饰的长方形
RedShapeDecorator redRectangle = new RedShapeDecorator(new Rectangle());
// 输出验证
circle.draw();
System.out.println("====================");
redCircle.draw();
System.out.println("====================");
redRectangle.draw();
System.out.println("====================");
}
}

运行结果

1
2
3
4
5
6
7
8
画圆
====================
画圆
Border Color: Red
====================
画一个长方形
Border Color: Red
====================

可以看到画圆和画长方形的时候都加上了红色的 Border

例子类图

Component:就是 Shape

ConcreteComponent: 就是 Rectangle Circle

Decorator:就是 ShapeDecorator

ConcreteDecorator:就是 RedShapeDecorator

调用时序图