设计模式探索:装饰器模式

1. 装饰器模式定义

装饰器模式(Decorator Pattern)

装饰器模式是一种结构型设计模式,允许向一个对象动态添加行为。在不改变类的接口的情况下,装饰器模式在原始类上增加额外的职责,并且支持多个装饰器嵌套使用。
在这里插入图片描述

装饰器模式代码示例

抽象构件类

/**
 * 抽象构件类
 * 该类声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。
 */
public abstract class Component {
    // 抽象方法,由具体构件和装饰类实现
    public abstract void operation();
}

具体构件类

/**
 * 具体构件类
 * 该类实现了抽象构件类的业务方法,是被装饰的对象。
 */
public class ConcreteComponent extends Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent: 基础功能实现");
    }
}

抽象装饰类

/**
 * 抽象装饰类
 * 该类是装饰者模式的核心,继承了抽象构件类,并持有一个抽象构件类型的对象引用。
 */
public abstract class Decorator extends Component {
    // 维持一个对抽象构件对象的引用
    protected Component component;

    // 注入一个抽象构件类型的对象
    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        // 调用原有业务方法
        component.operation();
    }
}

具体装饰类

/**
 * 具体装饰类
 * 该类是装饰者模式的具体实现类,向构件添加新的职责。
 */
public class ConcreteDecorator extends Decorator {
    public ConcreteDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation(); // 调用原有业务方法
        addedBehavior(); // 调用新增业务方法
    }

    // 新增业务方法
    public void addedBehavior() {
        System.out.println("ConcreteDecorator: 新增业务功能");
    }
}

客户端使用示例

public class Client {
    public static void main(String[] args) {
        // 创建具体构件对象
        Component component = new ConcreteComponent();
        
        // 使用装饰类进行装饰
        Component decoratedComponent = new ConcreteDecorator(component);
        
        // 调用装饰后的方法
        decoratedComponent.operation();
    }
}

输出结果

ConcreteComponent: 基础功能实现
ConcreteDecorator: 新增业务功能

解析

  • 抽象构件类(Component):声明了具体构件和装饰类中实现的业务方法,使得客户端能以一致的方式处理未装饰和已装饰对象。
  • 具体构件类(ConcreteComponent):实现了抽象构件类的业务方法,是被装饰的对象。
  • 抽象装饰类(Decorator):继承了抽象构件类,持有一个抽象构件类型的对象引用,并实现了业务方法,通过调用引用对象的方法实现对业务方法的调用。
  • 具体装饰类(ConcreteDecorator):继承了抽象装饰类,实现了新增的业务方法。

通过这种设计模式,装饰器可以在不修改原始类代码的情况下,为原始类添加新的功能,并且支持多个装饰器的嵌套使用,从而灵活地增强原始类的功能。

2. 装饰器模式与代理模式的区别

代理模式(Proxy Pattern)

代理模式也是一种结构型设计模式,为其他对象提供一个代理,以控制对这个对象的访问。代理模式的主要目的是控制访问,而非增强功能。
在这里插入图片描述

  1. 目的意图不同

    • 装饰器模式:主要是为了增强目标类的功能。
    • 代理模式:主要是为了控制对目标类的访问。
  2. 使用差别

    • 装饰器模式:装饰器对目标对象没有控制权,目标对象的方法一定会被执行。
    • 代理模式:代理对象对目标对象有控制权,可以选择执行或不执行目标对象的方法。
  3. 对于客户端的关注点

    • 装饰器模式:客户端更关心的是对目标对象进行增强后的功能。
    • 代理模式:客户端更关心的是被代理对象的功能。

3. 装饰器模式在实际开发中的应用

**需求:**有多个装饰时是怎么保证后面的装饰,在前面装饰的基础上装饰的。比如字符,需要加密+压缩。怎么能让压缩,在加密的基础上压缩?

3.1 创建字符组件接口

public interface StringComponent {
    String transform(String str);
}

3.2 实现字符组件

// 字符组件
public class StringEncryptor implements StringComponent {
    @Override
    public String transform(String str) {
        // base64编码
        return Base64.getEncoder().encodeToString(str.getBytes());
    }
}

3.3 字符加密装饰器

public class StringEncryptorDecorator implements StringComponent {
    private StringComponent component;

    public StringEncryptorDecorator(StringComponent component) {
        this.component = component;
    }

    @Override
    public String transform(String str) {
        String encrypted = component.transform(str); // 调用前面一个装饰器或组件的方法
        // 这里演示一个简单的压缩方法,将字符串压缩成一行
        return encrypted.replaceAll("\\s+", "");
    }
}

3.4 字符压缩的装饰器

public class StringCompressorDecorator implements StringComponent {
    private StringComponent component;

    public StringCompressorDecorator(StringComponent component) {
        this.component = component;
    }

    @Override
    public String transform(String str) {
        String compressed = component.transform(str); // 调用前面一个装饰器或组件的方法
        // 这里演示一个简单的压缩方法,将字符串压缩成一行
        return compressed.replaceAll("\\s+", "");
    }
}

3.5 客户端

public class Client {
    public static void main(String[] args) {
        StringComponent component = new StringEncryptor(); // 创建字符加密组件
        component = new StringEncryptorDecorator(component); // 用字符加密装饰器装饰它
        component = new StringCompressorDecorator(component); // 用字符压缩装饰器再次装饰它

        String original = "Hello, world!"; // 原始字符串
        String transformed = component.transform(original); // 转换后的字符串
        System.out.println(transformed);
    }
}

输出结果为:SGVsbG8sIHdvcmxkIQ==,这是对原始字符串进行加密和压缩后的结果。可以看到,压缩操作在加密操作的基础上进行了。

4. 装饰器模式总结

装饰器模式概述

装饰器模式是一种结构型设计模式,旨在动态地给对象添加额外的职责。

优点:

  1. 灵活性: 装饰器模式允许在运行时通过添加装饰器来扩展对象的功能,比静态继承更加灵活。
  2. 可扩展性: 可以对一个对象进行多次装饰,以实现不同的行为或功能。
  3. 低耦合度: 装饰器模式允许开发者在不修改对象本身的情况下增加新功能。
  4. 开闭原则: 符合开闭原则,即对扩展开放,对修改封闭。

缺点:

  1. 对象数量多: 装饰器模式可能会产生许多小的装饰器对象,增加系统的复杂性。
  2. 错误机会多: 由于装饰器数量可能很多,增加了出错的机会。
  3. 性能问题: 装饰器模式可能会引入额外的性能开销,尤其是在多层装饰的情况下。

适用场景:

  1. 动态添加职责: 当需要动态地给对象添加职责,而不是通过继承增加子类。
  2. 透明性: 需要保持对象的接口不变,即装饰前后对象的接口完全一致。
  3. 不支持继承: 在不支持或不便于使用继承来扩展功能的场景。

相关推荐

  1. 装饰设计模式

    2024-07-13 21:34:02       46 阅读
  2. 设计模式装饰模式

    2024-07-13 21:34:02       61 阅读
  3. 设计模式装饰模式

    2024-07-13 21:34:02       31 阅读
  4. 设计模式 —— 装饰模式

    2024-07-13 21:34:02       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-13 21:34:02       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-13 21:34:02       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-13 21:34:02       58 阅读
  4. Python语言-面向对象

    2024-07-13 21:34:02       69 阅读

热门阅读

  1. 数据湖仓一体(六)安装flink

    2024-07-13 21:34:02       21 阅读
  2. 牛客小白月赛96 C-最多数组的数量

    2024-07-13 21:34:02       23 阅读
  3. 3011.判断一个数组是否可以变为有序

    2024-07-13 21:34:02       23 阅读
  4. Spring是如何管理事务的?

    2024-07-13 21:34:02       25 阅读
  5. Kylin的智能优化:Cube自动优化的奥秘

    2024-07-13 21:34:02       18 阅读