设计模式之装饰器模式

概念

装饰器模式(Decorator Pattern)是一种结构型设计模式,它向对象添加功能而无需修改对象本身。通过创建一个装饰器类来包装原始类,可以在不通过修改原始类的情况下,扩展对象的功能。


装饰器模式的角色

装饰器模式中通常包括以下几种角色:

① Component(抽象构件):是装饰器模式中需要装饰的对象的抽象基类或者接口,定义了对象操作的基本方法,可以是抽象类、接口或者普通的类。

② ConcreteComponent(具体构件):是实现Component接口的具体对象,在程序运行时,它将被装饰器装饰。

③ Decorator(抽象装饰器):该角色是所有具体装饰器的父类,包含一个Component类型的成员变量component,它是被装饰者的引用。同时,也实现了Component接口,保证了装饰器和被装饰对象都具有相同的操作接口。

④ConcreteDecorator(具体装饰器):具体装饰器是实现Decorator接口的子类,包含了一个Component类型的成员变量component,它是被装饰对象的引用。具体装饰器可以被多次装饰,实现了对被装饰对象的递归装饰。具体装饰器的实现类可以有多个。

⑤ Client(客户端):客户端程序通常包括创建被装饰对象、创建具体装饰器对象以及执行装饰器的操作等步骤。它可以使用装饰器来扩展对象的行为,也可以通过组合不同的装饰器来实现不同的功能,从而完成特定的任务。


装饰器模式的应用场景

① 在不影响其他对象的情况下,对单个对象的行为或属性进行动态扩展或削减,使得其功能更加灵活且易于维护。

② 当需要在对象的不同层次上动态地添加或删除功能时,装饰器模式可以提供更加灵活的方式,避免了使用继承造成的类爆炸现象。

③ 当不能采用继承方式对系统原有类进行扩展或者不希望通过继承来增加子类数目时,装饰器模式是一种更加灵活和好用的方案。

④ 当需要组合多个装饰器进行加强时,装饰器模式可以提供更加灵活的选择,使得装饰器之间可以根据需要任意组合,避免了继承中静态特性所导致的组合困难问题。

⑤ 当需要在一个类中,添加新的行为或属性,但又不想增加过多的子类时,装饰器模式可以提供一种更加灵活的方式,使得新增加的行为和属性可以根据需要进行随时添加和删除。


java举例说明装饰器模式

我们假设现有一个 Shape 接口,它定义了一个抽象方法 draw(),表示要绘制一个形状。同时,我们有一个实现了 Shape 接口的具体类 Rectangle,表示一个矩形。现在,我们想要给这个矩形添加边框的功能。这时候,就可以用装饰器模式实现。
① Component(抽象构件角色)
Shape 接口就是抽象构件角色,它定义了一个 draw() 方法,表示要绘制一个形状。

public interface Shape {
    void draw();
}

② ConcreteComponent(具体构件角色)
Rectangle 类就是具体构件角色,实现了 Shape 接口的 draw() 方法,表示绘制了一个矩形。

public class Rectangle implements Shape {

    @Override
    public void draw() {
        System.out.println("Shape: Rectangle");
    }
}

③ Decorator(抽象装饰角色)
ShapeDecorator 就是抽象装饰角色,它实现了 Shape 接口,并持有一个 Shape 对象的引用,表示对这个对象进行装饰。它还定义了一个 draw() 方法,其中调用了持有的 Shape 对象的 draw() 方法,并加上了装饰自己的功能。

public abstract class ShapeDecorator implements Shape {
    protected Shape decoratedShape;

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

    public void draw() {
        decoratedShape.draw();
    }
}

④ ConcreteDecorator(具体装饰角色)
RedShapeDecorator 就是具体装饰角色,它继承了 ShapeDecorator,并添加了一个方法 setRedBorder(),表示给这个形状加上了红色边框。在实现 draw() 方法时,它首先调用基类的 draw() 方法,然后添加上自己的装饰功能。

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");
    }
}

有了上述几个角色,我们就可以实现给 Rectangle 加上红色边框的功能了。如下所示:

Shape rectangle = new Rectangle();
Shape redRectangle = new RedShapeDecorator(new Rectangle());

System.out.println("Rectangle with normal border:");
rectangle.draw();

System.out.println("\nRectangle of red border:");
redRectangle.draw();

输出结果如下:

Rectangle with normal border:
Shape: Rectangle

Rectangle of red border:
Shape: Rectangle
Border Color: Red

从输出结果可以看出,rectangle.draw()只有draw()的功能,而redRectangle.draw()多了一个添加颜色的功能。

UML类图如下:
UML类图


装饰器模式在框架当中的应用

① Mybatis 中的装饰器模式
Mybatis 框架中的装饰器模式主要体现在插件(Interceptor)上。插件是 Mybatis 中最常用的扩展机制,它允许在 Mybatis 中注入拦截器,从而拦截一些特定的动作,修改它们的返回值或者加上一些自定义行为。插件可以应用于语句执行、处理结果集、事务管理等方面。在 Mybatis 中,所有的拦截器都必须实现 Interceptor 接口,并重写其 intercept() 方法。这个方法会在 Mybatis 执行的每个步骤中被调用,从而在其中添加一些额外的行为或者修改行为的结果。这就是 Mybatis 中的装饰器模式,通过拦截器实现对 Mybatis 的增强,并且不改变 Mybatis 的原有逻辑。

② Spring 中的装饰器模式
Spring 框架中的装饰器模式主要体现在装饰器模式和AOP结合使用中。在 Spring 中,我们可以使用 AOP 在切面上应用装饰器模式,从而实现对 Spring IoC 容器
中的 Bean 进行增强。通过 AOP,我们可以在 Spring 中使用装饰器模式来动态地添加额外的行为,而无需修改原有代码,提高了代码可维护性和灵活性。例如,我们可以使用 Spring AOP 来维护事务,加入缓存或者应用统计逻辑等等,这都是使用装饰器模式进行增强的表现。


装饰器模式和代理模式的区别

装饰器模式和代理模式都是结构型设计模式,它们都是在不修改原有代码的情况下,给对象添加一些新功能。但是,这两种模式在实现的方法和用途上有一些不同,下面是它们之间的区别:

① 实现方式不同
装饰器模式和代理模式,在实现时采用的方式不同。装饰器模式是通过将一个装饰对象嵌套在原始对象内部,动态地给对象添加新的行为或者属性。而代理模式是通过创建一个代理对象,替代原有对象的位置,控制对原始对象的访问,并在访问前后执行一些额外的操作。

② 目的不同
装饰器模式的主要目的是为了扩展对象功能,让对象拥有更多的行为和属性,同时也要保留原有功能和接口。而代理模式的主要目的是为了控制对象的访问,并在访问前后执行一些额外的操作,如安全检查、远程连接等。

③运用场景不同
装饰器模式常常用于需要动态地给对象增加新的操作或者修改现有操作方式的场景中,而代理模式常常用于需要在原有操作方式基础上进行一些额外控制或增强的场景中,如权限校验、性能优化等。

④关注点不同
装饰器模式关注的是对象的功能扩展或属性变化,其目的是为了让对象功能更加灵活和易于维护。而代理模式的关注点是对象的安全和访问控制,其目的是为了保证对象的安全和访问可控性。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代号diitich

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值