装饰器模式

一、实现原理

装饰器设计模式(Decorator)是一种结构型设计模式 ,它允许动态地为对象添加新的行为 。它通过创建一个包装器来实现,即将对象放入一个装饰器类 中,再将装饰器类放入另一个装饰器类中,以此类推,形成一条包装链 。这样,我们可以在不改变原有对象 的情况下,动态地添加新的行为或修改原有行为

在 Java 中,实现装饰器设计模式的步骤如下:

1、定义一个接口或抽象类,作为被装饰对象的基类。

java 复制代码
public interface Component {
    void operation();
}

在这个示例中,我们定义了一个名为 Component 的接口,它包含一个名为 operation 的抽象方法,用于定义被装饰对象的基本行为。

2、定义一个具体的被装饰对象,实现基类中的方法。

java 复制代码
public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("ConcreteComponent is doing something...");
    }
}

3、定义一个抽象装饰器类,继承基类,并将被装饰对象作为属性。

java 复制代码
public abstract class Decorator implements Component {

    protected Component component;

    public Decorator(Component component) {
        this.component = component;
    }

    @Override
    public void operation() {
        component.operation();
    }
}

在这个示例中,我们定义了一个名为 Decorator 的抽象类,继承了 Component 接口,并将被装饰对象作为属性。在 operation 方法中,我们调用被装饰对象的同名方法。

4、定义具体的装饰器类,继承抽象装饰器类,并实现增强逻辑。

java 复制代码
public class ConcreteDecoratorA extends Decorator {

    public ConcreteDecoratorA(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        super.operation();
        System.out.println("ConcreteDecoratorA is adding new behavior...");
    }
}

在这个示例中,我们定义了一个名为 ConcreteDecoratorA 的具体装饰器类,继承了 Decorator 抽象类,并实现了 operation 方法的增强逻辑。在 operation 方法中,我们先调用被装饰对象的同名方法,然后添加新的行为。

5、使用装饰器增强被装饰对象。

java 复制代码
public class Main {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        component = new ConcreteDecoratorA(component);
        component.operation();
    }
}

在这个示例中,我们先创建了一个被装饰对象 ConcreteComponent,然后通过 ConcreteDecoratorA 类创建了一个装饰器,并将被装饰对象作为参数传入。最后,调用装饰器的 operation 方法,这样就可以实现对被装饰对象的增强。

二、使用场景

在 Java 中,装饰器模式的应用非常广泛,特别是在 I/O 操作中。Java 中的 I/O 类库就是使用装饰器模式来实现不同的数据流之间的转换和增强的。

我们打开文件 a.txt,从中读取数据。其中,InputStream 是一个抽象类,FileInputStream 是专门用来读取文件流的子类。BufferedInputStream 是一个支持带缓存功能的数据读取类,可以提高数据读取的效率,具体的代码如下:

java 复制代码
@Test
    public void testIO() throws Exception {
        InputStream inputStream = new FileInputStream("C:/bbb/a.txt");
        //实现了包装
        inputStream = new BufferedInputStream(inputStream);
        byte[] bytes = new byte[1024];
        int len;
        while((len = inputStream.read(bytes)) != -1){
            System.out.println(new String(bytes, 0, len));
        }
    }

其中BufferedInputStream对读取数据做了增强。

这样看来,装饰器设计模式和代理模式好像有点相似,接下来就来讨论一下它们之间的区别。

三、和代理模式的区别:

代理模式的目的是为了控制对对象的访问,它在对象的外部提供一个代理对象来控制对原始对象的访问。代理对象和原始对象通常实现同一个接口或继承同一个类,以保证二者可以互相替代。
装饰器模式的目的是为了动态地增强对象的功能 ,它在对象的内部通过一种包装器的方式来实现。装饰器模式中,装饰器类和被装饰对象通常实现同一个接口或继承同一个类,以保证二者可以互相替代。装饰器模式也被称为包装器模式。

代理模式中,代理类附加的是跟原始类无关的功能。

比如说,我们给service层中的每个方法的特定位置加上日志,日志本身与我们的业务逻辑并不是强相关的,而且我们之后也一般不会使用到原始对象了,而是直接面向代理开发,使用代理中的方法,代理模式的初衷是屏蔽原始对象并增强功能。

装饰器模式中**,装饰器类附加的是跟原始类相关的增强功能。**

就比如说上面的例子,BufferInputStream包装了一个FileInputStream,对原始对象进行了增强,而且装饰器模式支持层层包装。我们会经常使用原始类,也经常使用包装类,使用方式更灵活了,装饰器模式可以让原来功能不够强大的对象逐渐变强。

相关推荐
Dave_Young4 天前
上位机开发中的设计模式(3):装饰器模式
设计模式·装饰器模式
颯沓如流星5 天前
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
java·重构·装饰器模式
佩奇的技术笔记14 天前
从Java的JDK源码中学设计模式之装饰器模式
java·设计模式·装饰器模式
何中应16 天前
【设计模式-3.5】结构型——装饰器模式
java·设计模式·装饰器模式
秋名RG23 天前
深入理解Java装饰器模式:动态扩展对象功能的优雅之道
java·python·装饰器模式
常某某的好奇心1 个月前
装饰模式(Decorator Pattern)
装饰器模式
lczdyx2 个月前
从Flask到智能体:装饰器模式在AI系统中的架构迁移实践
人工智能·python·语言模型·架构·flask·装饰器模式
星星点点洲2 个月前
【设计模式区别】装饰器模式和适配器模式区别
设计模式·适配器模式·装饰器模式
程序员JerrySUN2 个月前
设计模式每日硬核训练 Day 12:装饰器模式(Decorator Pattern)完整讲解与实战应用
设计模式·装饰器模式
aiden:)2 个月前
星巴克咖啡下单系统:UML 类图解析与代码实现
设计模式·软件工程·uml·装饰器模式