Java设计模式之装饰者模式详解和代码实例

Java设计模式之装饰者模式详解和代码实例

什么是装饰者模式?

装饰者模式是一种结构型设计模式,以动态的方式将责任附加到对象上。装饰者提供了与继承相比更为灵活的替代方案,以扩展功能。

装饰者模式的组成

  • 抽象构件(Component):定义装饰者和被装饰者的公共接口。
  • 具体构件(ConcreteComponent):这是被装饰者,这是需要进行功能扩展的对象。
  • 装饰者(Decorator):这是包含被装饰者的实例,装饰者将在被装饰者的行为前面或后面添加一些自己的行为。
  • 具体装饰者(ConcreteDecorator):这个组件通过添加自己的行为来扩展与具体构件(ConcreteComponent)相关联的对象的功能。

装饰者模式的优缺点

优点

  • 可以动态的扩展一个对象的功能,而继承无法实现这一点。
  • 可以使用多个具体装饰者封装具体构件类形成复合装饰者,从而实现各种不同的装饰效果。
  • 装饰者模式符合开闭原则,可以在不修改原有代码的基础上,增加功能或修改装饰器的行为。

缺点

  • 使用装饰者模式会产生许多小对象,在一定程序上会增加系统的复杂性和理解难度。
  • 装饰者模式会改变对象之间的关系,增加对象的嵌套深度,加重了程序的运行负载,可能会导致性能问题。

装饰者模式的代码实例

下面是一个简单的装饰者模式的实例。

示例一:咖啡店

我们来看一个咖啡店的例子,想要给咖啡加上牛奶、糖、摩卡等等,同时也可能会有不加任何调料的咖啡。

// 抽象构件
interface Beverage {
    int cost();// 获取饮料价格
    String getDescription();// 获取饮料描述
}
// 具体构件
class Coffee implements Beverage {
    private int cost = 10;
    @Override
    public int cost() {
        return cost;
    }
    @Override
    public String getDescription() {
        return "纯咖啡";
    }
}
// 装饰器
class AddonDecorator implements Beverage {
    private Beverage beverage;
    AddonDecorator(Beverage beverage) {
        this.beverage = beverage;
    }
    @Override
    public int cost() {
        return this.beverage.cost();
    }
    @Override
    public String getDescription() {
        return this.beverage.getDescription();
    }
}
// 具体装饰器
class Sugar extends AddonDecorator {
    Sugar(Beverage beverage) {
        super(beverage);
    }
    @Override
    public int cost() {
        return super.cost() + 2;
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " 加糖";
    }
}
class Milk extends AddonDecorator {
    Milk(Beverage beverage) {
        super(beverage);
    }
    @Override
    public int cost() {
        return super.cost() + 3;
    }
    @Override
    public String getDescription() {
        return super.getDescription() + " 加牛奶";
    }
}
// 测试类
public class TestDecorator {
    public static void main(String[] args) {
        // 纯咖啡
        Beverage beverage = new Coffee();
        System.out.println("纯咖啡价格:" + beverage.cost() + ", 描述:" + beverage.getDescription());

        // 加糖咖啡
        beverage = new Sugar(beverage);
        System.out.println("加糖咖啡价格:" + beverage.cost() + ", 描述:" + beverage.getDescription());

        // 加牛奶咖啡
        beverage = new Milk(beverage);
        System.out.println("加牛奶咖啡价格:" + beverage.cost() + ", 描述:" + beverage.getDescription());

        // 加糖加牛奶咖啡
        beverage = new Milk(new Sugar(new Coffee()));
        System.out.println("加糖加牛奶咖啡价格:" + beverage.cost() + ", 描述:" + beverage.getDescription());
    }
}

在上面的例子中,Beverage 是抽象构件,Coffee 是具体构件,AddonDecorator 是装饰器,SugarMilk都是具体装饰器。

示例二:文件读写

下面是一个文件读写的例子。我们要为文件读写增加加密、压缩等其他操作。

// 文件操作接口,抽象构件
interface FileOperation {
    void write(String text);
    String read();
}
// 具体文件操作类,也是具体构件
class TextFile implements FileOperation {
    private String fileName;
    TextFile(String fileName) {
        this.fileName = fileName;
    }
    @Override
    public void write(String text) {
        System.out.println("Write to " + fileName + ": " + text);
    }
    @Override
    public String read() {
        return "Text from " + fileName;
    }
}
// 文件操作装饰器
class FileDecorator implements FileOperation {
    private FileOperation file;
    FileDecorator(FileOperation file) {
        this.file = file;
    }
    @Override
    public void write(String text) {
        file.write(text);
    }
    @Override
    public String read() {
        return file.read();
    }
}
// 具体文件加密装饰器
class EncryptedFileDecorator extends FileDecorator {
    EncryptedFileDecorator(FileOperation file) {
        super(file);
    }
    @Override
    public void write(String text) {
        text = text + " [encrypted]";
        super.write(text);
    }
    @Override
    public String read() {
        String text = super.read();
        return text.replace("[encrypted]", "");
    }
}
// 具体文件压缩装饰器
class CompressedFileDecorator extends FileDecorator {
    CompressedFileDecorator(FileOperation file) {
        super(file);
    }
    @Override
    public void write(String text) {
        text = text + " [compressed]";
        super.write(text);
    }
    @Override
    public String read() {
        String text = super.read();
        return text.replace("[compressed]", "");
    }
}
// 测试类
public class TestFileDecorator {
    public static void main(String[] args) {
        //不加任何操作
        FileOperation file = new TextFile("test.txt");
        file.write("Hello World");
        System.out.println("Read from file: " + file.read());

        //加密操作
        file = new EncryptedFileDecorator(file);
        file.write("Hello World");
        System.out.println("Read from file: " + file.read());

        //压缩操作
        file = new CompressedFileDecorator(file);
        file.write("Hello World");
        System.out.println("Read from file: " + file.read());

        //加密和压缩操作
        file = new CompressedFileDecorator(new EncryptedFileDecorator(new TextFile("test.txt")));
        file.write("Hello World");
        System.out.println("Read from file: " + file.read());
    }
}

在上面的例子中,FileOperation 是抽象构件,TextFile 是具体构件,FileDecorator是装饰器,EncryptedFileDecoratorCompressedFileDecorator是具体装饰器。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java设计模式之装饰者模式详解和代码实例 - Python技术站

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • Java实现的简单画图板示例

    下面是关于“Java实现的简单画图板示例”的完整攻略。 Java实现的简单画图板示例 概述 本示例是使用Java编写的一个简单画图板,可以通过鼠标创建、选择、移动和删除图形,并支持对图形进行颜色和填充操作。 开发环境 Java实现的简单画图板示例需要在开发环境下进行编写,推荐使用Java集成开发环境(IDE)Eclipse进行开发。在Eclipse中,您需要…

    Java 2023年5月19日
    00
  • Jdbc连接数据库基本步骤详解

    以下是 Jdbc 连接数据库基本步骤的详细攻略: 步骤一:加载驱动程序 在 Java 中,要使用 JDBC 连接数据库,需要先加载相应的数据库驱动。具体步骤为: Class.forName("com.mysql.jdbc.Driver"); 其中 com.mysql.jdbc.Driver 是 MySQL 数据库的驱动程序名,其他数据库的…

    Java 2023年5月20日
    00
  • JVM内存增强之逃逸分析

    JVM内存增强之逃逸分析是指在Java应用程序启动时,JVM在运行过程中动态的分析程序的对象生命周期,将对象的使用范围限制在方法内部,从而达到减少对象在堆上的分配、减少GC(垃圾回收)压力、提高应用程序的性能等目的的一种技术手段。 下面是JVM内存增强之逃逸分析的完整攻略: 1. 什么是逃逸分析? 逃逸分析是一种程序优化技术,它对程序中的对象进行分析,识别出…

    Java 2023年5月19日
    00
  • Java简单计时的实现案例(可以用来限时循环)

    让我们来详细讲解一下“Java简单计时的实现案例(可以用来限时循环)”的完整攻略。 思路概述 实现计时器的基本思路如下: 设置一个计时器变量,反映经过的时间。 确定计时器启动时刻。 定时器中执行要计时的动作(循环等)。 规定计时器结束条件,一般用时间限制或者次数限制。 计算执行完毕所需时间。 输出结果等。 根据这个思路,我们可以实现一个简单可用的计时器。 示…

    Java 2023年5月19日
    00
  • JavaSpringBoot报错“HttpMessageNotWritableException”的原因和处理方法

    原因 “HttpMessageNotWritableException” 错误通常是以下原因引起的: 响应体不正确:如果响应体不正确,则可能会出现此错误。在这种情况下,您需要检查响应体并确保它们正确。 响应体格式不正确:如果响应体格式不正确,则可能会出现此错误。在这种情况下,您需要检查响应体格式并确保它们正确。 解决办法 以下是解决 “HttpMessage…

    Java 2023年5月4日
    00
  • uni-app 微信小程序授权登录的实现步骤

    下面是详细讲解“uni-app 微信小程序授权登录的实现步骤”的完整攻略: 一、前置条件 在进行微信小程序授权登录之前,要确保以下几个前置条件已经满足: 已经注册微信小程序开发者账号,并创建了一个小程序。 在小程序后台设置了合法的“授权域名”。 在小程序后台开启了“用户信息”,并获取了对应的“AppID”和“AppSecret”。 二、授权登录实现步骤 接下…

    Java 2023年5月23日
    00
  • SpringMVC中使用@PathVariable绑定路由中的数组的方法

    SpringMVC中使用@PathVariable绑定路由中的数组的方法 在SpringMVC中,我们可以使用@PathVariable注解将路由中的参数绑定到方法的参数上。如果路由中的参数是一个数组,我们可以使用@PathVariable注解来绑定它。本文将详细讲解SpringMVC中使用@PathVariable绑定路由中的数组的方法。 1. 绑定路由中…

    Java 2023年5月18日
    00
  • springboot+idea+maven 多模块项目搭建的详细过程(连接数据库进行测试)

    下面详细讲解一下如何使用Spring Boot、IDEA和Maven搭建多模块项目并连接数据库测试。 环境准备 在开始之前,确保你已经安装了以下环境: JDK 1.8或以上版本 IDEA集成开发环境 Maven构建工具 数据库(本次示例使用MySQL) 创建Maven多模块项目 打开IDEA,点击File -> New -> Project,选择…

    Java 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部