4.装饰器模式(结构型)-灵析社区

菜鸟码转

四、装饰器模式(结构型)

装饰器设计模式是一种结构型的设计模式,它允许我们在运行时动态地给一个对象添加额外的行为,并且不需要修改原有的类。它可以有效地避免类爆炸问题,提高代码的可维护性和复用性。同时,装饰器模式也具有灵活、可扩展和易于维护等优点,是一种非常实用和常用的设计模式。

使用装饰器模式时,我们将新增的行为包装在一个装饰器类中,与原有类具有相同的接口。这个装饰器类可以包含一个对于原有类的引用,在调用原有类的方法之前或之后执行额外的逻辑,从而实现对原有类的增强。

装饰器模式的核心思想就是「包装」,通过不断地向对象上叠加新的行为,使得对象具有了更多的功能和特性,同时保持了对象的原有接口和结构不变。

下面是装饰器模式的几个要点:

  • 定义一个基础组件(或者抽象组件):基础组件定义了对象的基本行为和属性,是装饰器的目标对象;
  • 创建一个装饰器类(或者抽象装饰器类):装饰器类与基础组件具有相同的接口,但是它包含一个指向基础组件对象的引用,并在执行操作前后加入额外的逻辑;
  • 创建具体的装饰器类:具体的装饰器类继承自装饰器类,并实现额外的逻辑;
  • 将对象包装在装饰器中:客户端代码可以将对象动态地包装在装饰器中,从而增强对象的功能和特性;
  • 可以通过链式调用来实现多个装饰器的组合:多个装饰器可以通过链式调用的方式依次包装在对象上,从而实现复杂的组合逻辑。

装饰器设计模式的应用场景

装饰器设计模式是一种结构型设计模式,它允许在运行时动态地扩展一个对象的功能。

以下是一些装饰器设计模式的应用场景:

  • 日志记录:我们可以使用装饰器来记录函数被调用的次数、参数、返回值等信息,从而实现日志记录功能;
  • 认证和授权:装饰器可以用于验证用户是否已经登录,并根据他们的权限来限制他们可以执行的操作;
  • 缓存:装饰器可以用于缓存函数返回的结果,以避免重复计算,提高性能;
  • 参数检查:装饰器可以用于检查函数的参数是否符合要求,如果不符合要求,则抛出异常或者执行其他操作;
  • 代码跟踪和分析:我们可以使用装饰器来追踪函数的执行过程,并收集性能数据或其他统计信息。

下面是一个常见的使用装饰器设计模式的例子:

  • 抽象被装饰者
package cn.leetcode;

public interface Drink {

    String description();

    float cost();

}
  • 抽象装饰者(装饰者基类)
package cn.leetcode;

public abstract class Decorator implements Drink{

    /**
     * 要装饰的对象
     */
    private Drink drink;

    public Decorator(Drink drink){
        this.drink = drink;
    }


    @Override
    public String description() {
        return drink.description();
    }

    @Override
    public float cost() {
        return drink.cost();
    }

}
  • 具体装饰者:纯豆浆、黑豆、鸡蛋
package cn.leetcode;

public class SoyaBeanMilk implements Drink {

    @Override
    public String description() {
        return "纯豆浆";
    }

    @Override
    public float cost() {
        return 5f;
    }

}
package cn.leetcode;

public class BlackBeanDecorator extends Decorator {

    public BlackBeanDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public String description() {
        return super.description() + " + 黑豆";
    }

    @Override
    public float cost() {
        return super.cost() + 3.0f;
    }

}
package cn.leetcode;

public class EggDecorator extends Decorator {

    public EggDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public String description() {
        return super.description() + " + 鸡蛋";
    }

    @Override
    public float cost() {
        return super.cost() + 2.0f;
    }

}
package cn.leetcode;

public class SugarDecorator extends Decorator {

    public SugarDecorator(Drink drink) {
        super(drink);
    }

    @Override
    public String description() {
        return super.description() + " + 糖";
    }

    @Override
    public float cost() {
        return super.cost() + 0.5f;
    }

}
  • 客户端
package cn.leetcode;

public class Client {

    public static void main(String[] args) {
        // 子类纯豆浆:包在最里面
        Drink soya = new SoyaBeanMilk();
        // 在豆浆中加鸡蛋
        EggDecorator eggSoya = new EggDecorator(soya);
        // 在加了鸡蛋的豆浆中加糖
        SugarDecorator sugarEggSoya = new SugarDecorator(eggSoya);
        // 加了糖的豆浆中加黑豆
        BlackBeanDecorator blackBeanSugarEggSoya = new BlackBeanDecorator(sugarEggSoya);

        System.out.println("顾客点的是:" + blackBeanSugarEggSoya.description());
        System.out.println("顾客一共消费了 " + blackBeanSugarEggSoya.cost() + " 元");
    }

}

输出:

顾客点的是:纯豆浆 + 鸡蛋 + 糖 + 黑豆
顾客一共消费了 10.5 元

总结

  • 装饰器设计模式是一种结构型设计模式,它允许在不改变原有对象的基础上,动态地添加新的行为或修改已有行为;
  • 通过将对象传递给装饰器函数或类,可以创建一个包装对象,该对象可以在执行原始对象的操作之前或之后执行其他操作;
  • 这种模式使得代码更加灵活和可扩展,而不需要在原始对象中硬编码所有可能的变体。

阅读量:2023

点赞量:0

收藏量:0