java 设计模式(二)装饰器模式

一、装饰器模式简介

装饰器模式是一种结构型设计模式,用于动态地将新功能附加到对象上。这种类型的设计模式属于对象的组合,通过组合对象来扩展功能,而不仅仅是通过继承关系。

1. 核心组成

  • Component(组件):定义了对象的接口,可以给这些对象动态地添加功能。
  • ConcreteComponent(具体组件):定义了Component接口的实现。
  • Decorator(装饰器):持有Component对象的引用,并定义了与Component接口一致的接口。
  • ConcreteDecorator(具体装饰器):实现了Decorator的接口,并添加了额外的功能。
    在这里插入图片描述

2. 适用场景

当需要为类添加功能时,且不希望使用继承或修改现有类时。
当需要通过一种方式包装对象,而这种方式不能通过生成子类实现时。

二、Java I/O中的装饰器模式

Java I/O库中,装饰器模式被用于为基本的输入/输出流添加额外的功能。例如,FilterInputStream 和 FilterOutputStream 是装饰器模式的实现,它们允许你为已有的输入/输出流添加过滤功能。

实现示例
让我们通过一个简单的例子来展示装饰器模式在Java I/O中的应用。

  1. 定义Component接口
public interface Output {
    void write(String data);
}
  1. 创建具体组件
public class ConsoleOutput implements Output {
    @Override
    public void write(String data) {
        System.out.println(data);
    }
}
  1. 创建装饰器
public abstract class Decorator implements Output {
    protected Output output;

    public Decorator(Output output) {
        this.output = output;
    }

    @Override
    public void write(String data) {
        output.write(data);
    }
}
  1. 创建具体装饰器
public class LoggingDecorator extends Decorator {
    public LoggingDecorator(Output output) {
        super(output);
    }

    @Override
    public void write(String data) {
        System.out.println("Logging: " + data);
        output.write(data);
    }
}
  1. 使用装饰器
public class Client {
    public static void main(String[] args) {
        Output console = new ConsoleOutput();
        Output loggingOutput = new LoggingDecorator(console);

        loggingOutput.write("Hello, World!");
    }
}

结果
执行上述代码,控制台输出将会是:

Logging: Hello, World!
Hello, World!

三 、示例代码

Java I/O库的设计充分利用了装饰器模式,使得开发者能够灵活地组合不同的流类型,以实现诸如缓冲、加密、压缩等功能,而无需直接修改基础流类。以InputStream为例,它是所有字节输入流的基类,而如BufferedInputStream、DataInputStream、GZIPInputStream等则是对InputStream的装饰,分别提供了缓冲、数据解析、gzip解压等功能。

1. 使用 BufferedInputStream 装饰 FileInputStream

import java.io.*;  
  
public class InputStreamDecoratorExample {  
    public static void main(String[] args) {  
        try (  
            // 创建一个 FileInputStream 对象,作为组件对象  
            InputStream fileInputStream = new FileInputStream("example.txt");  
            // 使用 BufferedInputStream 装饰 FileInputStream,增加缓冲功能  
            InputStream bufferedInputStream = new BufferedInputStream(fileInputStream)  
        ) {  
            // 读取数据(这里只是简单示例,实际使用中会循环读取直到文件末尾)  
            int data = bufferedInputStream.read();  
            while (data != -1) {  
                // 处理读取到的数据...  
                System.out.print((char) data);  
                data = bufferedInputStream.read();  
            }  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

在这个示例中,我们首先创建了一个 FileInputStream 对象来从文件中读取数据。然后,我们创建了一个 BufferedInputStream 对象,并将 FileInputStream 对象传递给它的构造函数。现在,我们可以通过 bufferedInputStream 对象来读取数据,而不需要直接使用 fileInputStream 对象。由于 BufferedInputStream 提供了缓冲功能,因此读取数据的性能可能会得到提高。最后,我们使用 try-with-resources 语句来自动关闭流,以确保资源得到正确释放。

2. 使用装饰器模式读取文件并打印

假设我们想从一个文件中读取数据,但希望在读取之前先进行缓冲以提高效率,同时对数据进行gzip解压缩。下面是如何使用Java IO装饰器模式实现这一需求的示例:

import java.io.*;
import java.util.zip.GZIPInputStream;

public class DecoratorPatternInJavaIO {

    public static void main(String[] args) {
        try (
            // 基础组件:文件输入流
            FileInputStream fileInputStream = new FileInputStream("example.txt.gz");
            // 装饰器1:添加gzip解压缩功能
            GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream);
            // 装饰器2:添加缓冲功能
            BufferedInputStream bufferedInputStream = new BufferedInputStream(gzipInputStream);
            // 使用 BufferedReader 读取行(虽然不是严格意义上的装饰器,但展示了组合使用)
            BufferedReader reader = new BufferedReader(new InputStreamReader(bufferedInputStream))
        ) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

四、应用场景总结

除了IO流之外,装饰器模式在多个领域有广泛的应用,下面列举几个实际应用场景:

1. 日志记录与性能监控

装饰器模式可以用来为已有代码添加日志记录或性能监控功能,而无需修改原有代码。例如,可以创建一个日志装饰器类,该类包装任何对象的方法调用,并在调用前后记录日志信息。

class LoggingDecorator {
    private final Object decorated;

    public LoggingDecorator(Object decorated) {
        this.decorated = decorated;
    }

    public void operation() {
        System.out.println("Logging before operation.");
        decorated.operation();
        System.out.println("Logging after operation.");
    }
}

2. 用户权限控制

在权限管理系统中,装饰器模式可以用来动态地给用户添加或移除权限。例如,可以创建一个基础用户类,然后使用装饰器类为其添加管理员、编辑、查看等不同权限。

interface User {
    void showPermissions();
}

class BasicUser implements User {
    @Override
    public void showPermissions() {
        System.out.println("Basic permissions.");
    }
}

class AdminDecorator extends BasicUser {
    private User user;

    public AdminDecorator(User user) {
        this.user = user;
    }

    @Override
    public void showPermissions() {
        user.showPermissions();
        System.out.println("Admin permissions added.");
    }
}

3. GUI组件的个性化定制

在图形用户界面(GUI)开发中,装饰器模式可以用来为标准组件添加额外的外观或行为,比如边框、背景色等,而不必为每一种可能的组合创建新的组件类。

interface Component {
    void display();
}

class BaseComponent implements Component {
    @Override
    public void display() {
        System.out.println("Displaying base component.");
    }
}

class BorderDecorator extends BaseComponent {
    private Component component;

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

    @Override
    public void display() {
        System.out.println("Adding border...");
        component.display();
    }
}
  1. 网络请求的缓存与重试策略
    在处理网络请求时,可以使用装饰器模式来添加缓存逻辑或实现重试机制,而不需要改动原始的请求发送逻辑。

这些例子展示了装饰器模式的灵活性和实用性,它能够在不修改原有类的基础上,通过组合的方式动态扩展对象的功能,符合“开闭原则”(Open-Closed Principle),即对扩展开放,对修改关闭。

  • 39
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值