在日常开发中,当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是终极类或者采用继承方式会产生大量的子类。这时候,我们该怎么办呢?我们可以使用装饰器器模式来解决这个问题,本文将从以下四个方面讲解装饰器器模式。
装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变现有对象的结构的情况下,动态地给对象增加一些额外的功能。装饰器模式通过创建一个包装对象(即装饰器)来包裹真实对象,并在保持真实对象的接口不变的前提下,为其提供额外的功能。装饰器模式可以在运行时根据需要选择不同的装饰器来组合和修改对象的行为。
推荐博主开源的 H5 商城项目waynboot-mall,这是一套全部开源的微商城项目,包含三个项目:运营后台、H5 商城前台和服务端接口。实现了商城所需的首页展示、商品分类、商品详情、商品 sku、分词搜索、购物车、结算下单、支付宝/微信支付、收单评论以及完善的后台管理等一系列功能。 技术上基于最新得 Springboot3.0、jdk17,整合了 MySql、Redis、RabbitMQ、ElasticSearch 等常用中间件。分模块设计、简洁易维护,欢迎大家点个 star、关注博主。
github 地址:https://github.com/wayn111/waynboot-mall
装饰器模式的优点有:
装饰器模式的缺点有:
装饰器模式适用于以下场景:
以下是一个实现装饰器模式的 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
装饰器模式可以将不同功能的单个模块规划至不同的装饰器类中,各装饰器类独立自主,各司其职。客户端可以根据自己的需求自由搭配各种装饰器,每加一层装饰就会有新的特性体现出来,巧妙的设计让功能模块层层叠加,装饰之上套装饰,最终使原始对象的特性动态地得到增强。
关注公众号【waynblog】每周分享技术干货、开源项目、实战经验、国外优质文章翻译等,您的关注将是我的更新动力!