• 设计模式-装饰器模式(Decorator)


    一、装饰器模式概述

    1.1 什么是装饰器模式

    装饰器模式是一种结构型设计模式,它允许在运行时扩展一个对象的功能,而不需要改变其现有结构。这种模式的核心思想是通过创建一个包装类(装饰器)来动态地增强或修改原有对象的行为。

    具体来说,装饰器模式的主要特点如下:

    • 1、不改变原有对象的结构和方法。
    • 2、通过创建一个与被装饰对象接口相同的装饰器类,实现对被装饰对象的包装。
    • 3、可以在不改变现有代码的基础上,动态地给一个对象增加新的功能。
    • 4、装饰器模式是继承的一个补充,提供了比继承更加灵活的方式来扩展对象的行为。
      尽管装饰器模式非常灵活且可扩展,适用于需要动态地为对象增加功能的场景,但过度使用这种模式可能会导致系统的复杂性增加。因此,在使用装饰器模式时,需要确保真正需要扩展的地方使用,而不是滥用。

    1.2 简单实现装饰器模式

    装饰器模式是一种结构型设计模式,它允许在运行时动态地扩展一个对象的功能,而不需要改变其现有结构。下面是一个简单的 Java 实现装饰器模式的示例:

    首先,我们创建一个接口 Component:

    public interface Component {
        void operation();
    }
    
    • 1
    • 2
    • 3

    然后,我们创建一个具体的组件类 ConcreteComponent:

    public class ConcreteComponent implements Component {
        @Override
        public void operation() {
            System.out.println("具体组件的操作");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来,我们创建一个抽象装饰器类 Decorator,它也实现了 Component 接口,并持有一个 Component 类型的对象:

    public abstract class Decorator implements Component {
        protected Component component;
    
        public Decorator(Component component) {
            this.component = component;
        }
    
        @Override
        public void operation() {
            component.operation();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    现在,我们可以创建具体的装饰器类,例如 ConcreteDecoratorA 和 ConcreteDecoratorB,它们分别在原有功能的基础上添加新的功能:

    public class ConcreteDecoratorA extends Decorator {
        public ConcreteDecoratorA(Component component) {
            super(component);
        }
    
        @Override
        public void operation() {
            System.out.println("装饰器 A 的操作");
            super.operation();
        }
    }
    
    public class ConcreteDecoratorB extends Decorator {
        public ConcreteDecoratorB(Component component) {
            super(component);
        }
    
        @Override
        public void operation() {
            System.out.println("装饰器 B 的操作");
            super.operation();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    最后,我们在客户端代码中使用装饰器模式:

    public class Client {
        public static void main(String[] args) {
            Component component = new ConcreteComponent();
            Component decoratorA = new ConcreteDecoratorA(component);
            Component decoratorB = new ConcreteDecoratorB(decoratorA);
            decoratorB.operation();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行客户端代码,输出结果如下:

    装饰器 B 的操作
    装饰器 A 的操作
    具体组件的操作
    
    • 1
    • 2
    • 3

    1.3 使用装饰器模式的注意事项

    • 1、装饰器模式适用于需要动态地为对象增加功能的场景,如果不需要动态扩展功能,则不必要使用装饰器模式。
    • 2、装饰器模式会增加系统的复杂性,因此应该谨慎使用,避免过度使用。
    • 3、装饰器模式要求被装饰的对象和装饰器类都必须实现相同的接口或继承相同的抽象类,否则无法进行装饰。
    • 4、装饰器模式可能会导致设计上的冗余,因为每个装饰器都需要持有一个被装饰对象的引用,这会导致系统中存在大量的引用关系。
    • 5、如果需要对多个对象进行同样的装饰操作,可以考虑使用代理模式或者享元模式来优化系统结构。

    二、装饰器模式的用途

    装饰器模式是一种结构型设计模式,它允许在不改变现有对象结构的情况下,动态地给该对象增加一些职责(即增加其额外功能)。这种模式的核心在于创建一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

    以下是装饰器模式的一些主要用途:

    • 1、动态地为一个对象添加新的功能,同时又不改变其结构。这可以帮助我们在不修改原有组件、接口或者类的情况下为其添加额外的功能。
    • 2、用于元类的使用情况,可以作为元类的一些简单替代方案。
    • 3、在Java AWT和Swing中广泛使用,如为按钮、文本框等组件添加新的功能。
    • 4、适用于Java I/O流,如BufferedReader、BufferedWriter等。通过装饰器模式,可以在不改变原有I/O流的基础上,为其增加新的功能。
    • 5、在Python中也有广泛应用,如GIL(Global Interpreter Lock)就是一个典型的装饰器模式的实现。

    三、装饰器模式的实现方式

    3.1 通过接口和抽象类实现

    通过定义一个接口或抽象类,然后创建具体的装饰器类来实现装饰器模式。这种方式适用于需要动态添加功能的场景。

    // 定义一个接口
    public interface Component {
        void operation();
    }
    
    // 定义一个具体组件
    public class ConcreteComponent implements Component {
        @Override
        public void operation() {
            System.out.println("具体组件的操作");
        }
    }
    
    // 定义一个抽象装饰器类
    public abstract class Decorator implements 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();
            addedFunction();
        }
    
        public void addedFunction() {
            System.out.println("新增的功能");
        }
    }
    
    // 客户端代码
    public class Client {
        public static void main(String[] args) {
            Component component = new ConcreteComponent();
            Component decorator = new ConcreteDecorator(component);
            decorator.operation();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    3.2 通过Java反射实现

    通过Java反射机制,可以在运行时动态地为对象添加新的功能。这种方式适用于需要根据条件动态改变行为的场景。

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class DecoratorDemo {
        public static void main(String[] args) {
            MyInterface myInterface = (MyInterface) Proxy.newProxyInstance(
                    MyInterface.class.getClassLoader(),
                    new Class[]{MyInterface.class},
                    new DecoratorInvocationHandler(new MyInterfaceImpl()));
            myInterface.doSomething();
        }
    }
    
    interface MyInterface {
        void doSomething();
    }
    
    class MyInterfaceImpl implements MyInterface {
        @Override
        public void doSomething() {
            System.out.println("原始方法");
        }
    }
    
    class DecoratorInvocationHandler implements InvocationHandler {
        private Object target;
    
        public DecoratorInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("装饰器开始执行");
            Object result = method.invoke(target, args);
            System.out.println("装饰器结束执行");
            return result;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    3.3 通过使用第三方库实现

    有一些第三方库提供了装饰器模式的实现,如Spring框架中的AOP(面向切面编程)模块。这些库通常提供了更加完善的功能和更好的性能。

  • 相关阅读:
    【SIGGRAPH 2023】解读Rerender A Video:Zero-Shot 视频翻译任务
    2023-09-07 LeetCode每日一题(修车的最少时间)
    深入浅出 -- 系统架构之微服务标准组件及职责
    【50关于Visual Studio 2019控制台输出中文出现乱码问题及解决办法】
    Ubuntu 安装 MySQL 8.23
    SringBoot快速实现参数校验
    5G用户常驻区域预判及网络支撑前置策略研究
    HTML5期末大作业:HTML+CSS茶叶官网网页设计实例 企业网站制作
    大数据之Hive(二)
    如何理解GAN神经网络
  • 原文地址:https://blog.csdn.net/miaoyl1234/article/details/134282931