装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变现有对象的结构的情况下,动态地给对象增加一些额外的功能。装饰器模式通过创建一个包装对象(即装饰器)来包裹真实对象,并在保持真实对象的接口不变的前提下,为其提供额外的功能。装饰器模式可以在运行时根据需要选择不同的装饰器来组合和修改对象的行为。
装饰器模式的优点有:
装饰器模式的缺点有:
装饰器模式适用于以下场景:
以下是一个实现装饰器模式的 java 示例代码
//抽象组件接口
public interface Shape {
void draw();
}
//具体组件类:圆形
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
//具体组件类:矩形
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
//抽象装饰器类
public abstract class ShapeDecorator implements Shape {
//持有一个抽象组件对象
protected Shape shape;
//构造方法
public ShapeDecorator(Shape shape) {
this.shape = shape;
}
//调用被包装对象的方法
@Override
public void draw() {
shape.draw();
}
}
//具体装饰器类:红色装饰器
public class RedShapeDecorator extends ShapeDecorator {
//构造方法
public RedShapeDecorator(Shape shape) {
super(shape);
}
//重写draw方法,在调用被包装对象的方法之前或之后添加新的功能
@Override
public void draw() {
//调用被包装对象的方法
super.draw();
//添加新的功能
setRedBorder();
}
//定义新的功能方法
private void setRedBorder() {
System.out.println("Setting red border");
}
}
//具体装饰器类:绿色装饰器
public class GreenShapeDecorator extends ShapeDecorator {
//构造方法
public GreenShapeDecorator(Shape shape) {
super(shape);
}
//重写draw方法,在调用被包装对象的方法之前或之后添加新的功能
@Override
public void draw() {
//调用被包装对象的方法
super.draw();
//添加新的功能
setGreenBorder();
}
//定义新的功能方法
private void setGreenBorder() {
System.out.println("Setting green border");
}
}
//测试类
public class DecoratorPatternDemo {
public static void main(String[] args) {
//创建一个圆形对象
Shape circle = new Circle();
//创建一个矩形对象
Shape rectangle = new Rectangle();
//创建一个红色装饰器对象,包装圆形对象
Shape redCircle = new RedShapeDecorator(circle);
//创建一个绿色装饰器对象,包装矩形对象
Shape greenRectangle = new GreenShapeDecorator(rectangle);
//调用各个对象的方法,展示不同的效果
System.out.println("Normal circle:");
circle.draw();
System.out.println("Normal rectangle:");
rectangle.draw();
System.out.println("Red circle:");
redCircle.draw();
System.out.println("Green rectangle:");
greenRectangle.draw();
}
}
输出结果如下:
Normal circle:
Drawing a circle
Normal rectangle:
Drawing a rectangle
Red circle:
Drawing a circle
Setting red border
Green rectangle:
Drawing a rectangle
Setting green border
要想再 Spring 项目中应用装饰器模式,只需对以上代码进行简单改造即可,
@Component
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
@Component
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle");
}
}
@Component
public class GreenShapeDecorator extends ShapeDecorator {
// 构造方法
public GreenShapeDecorator(@Qualifier("rectangle") Shape shape) {
super(shape);
}
// 重写draw方法,在调用被包装对象的方法之前或之后添加新的功能
@Override
public void draw() {
// 调用被包装对象的方法
super.draw();
// 添加新的功能
setGreenBorder();
}
// 定义新的功能方法
private void setGreenBorder() {
System.out.println("Setting green border");
}
}
@Component
public class RedShapeDecorator extends ShapeDecorator {
// 构造方法
public RedShapeDecorator(@Qualifier("circle") Shape shape) {
super(shape);
}
// 重写draw方法,在调用被包装对象的方法之前或之后添加新的功能
@Override
public void draw() {
// 调用被包装对象的方法
super.draw();
// 添加新的功能
setRedBorder();
}
// 定义新的功能方法
private void setRedBorder() {
System.out.println("Setting red border");
}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class DecoratorTest {
// 从Spring容器中获取Context对象
@Autowired
private RedShapeDecorator redCircle;
@Autowired
private GreenShapeDecorator greenRectangle;
@Test
public void test() {
System.out.println("Red circle:");
redCircle.draw();
System.out.println("Green rectangle:");
greenRectangle.draw();
}
}
输出结果如下:
Red circle:
Drawing a circle
Setting red border
Green rectangle:
Drawing a rectangle
Setting green border
装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中,各装饰器类独立自主,各司其职。客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来,巧妙的设计让功能模块层层叠加,装饰之上套装饰,最终使原始对象的特性动态地得到增强。