装饰大师——装饰模式(Java实现)

news2024/11/26 12:21:29

引言

大家好,上期我们介绍了装饰模式在Python中的实现,今天,我们将继续探讨装饰模式,并展示如何在Java中实现它。

装饰模式概述

装饰模式的核心思想是将功能附加到对象上,而不是通过继承来实现,这种模式包含以下几个关键组成部分:

  1. 组件接口:定义基本功能;
  2. 具体组件:实现基本功能的类;
  3. 装饰器基类:实现组件接口,并包含一个指向组件对象的引用;
  4. 具体装饰器:扩展装饰器基类,实现额外的功能。

装饰模式与其他设计模式(如代理模式、适配器模式)不同之处在于,装饰模式注重动态地为对象添加职责,而不改变对象的接口。

模式结构

类图

示意图

装饰模式的Java实现

在Java中,装饰模式通常通过继承和组合来实现。以下是几种常见的实现方式:

基本实现

以下是一个简单的装饰器例子,它为组件添加打印日志的功能:

// 组件接口
interface Component {
    void operation();
}

// 具体组件
class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("Executing operation in ConcreteComponent");
    }
}

// 装饰器基类
abstract class Decorator implements Component {
    protected Component component;

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

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

// 具体装饰器
class LoggingDecorator extends Decorator {
    public LoggingDecorator(Component component) {
        super(component);
    }

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

// 测试
public class DecoratorPatternExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decoratedComponent = new LoggingDecorator(component);
        decoratedComponent.operation();
    }
}
多层装饰器的使用

装饰器可以叠加使用,实现多层装饰:

class UppercaseDecorator extends Decorator {
    public UppercaseDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        System.out.println("Converting to uppercase");
        super.operation();
        System.out.println("Converted to uppercase");
    }
}

public class MultiDecoratorExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component decoratedComponent = new LoggingDecorator(new UppercaseDecorator(component));
        decoratedComponent.operation();
    }
}

实际应用案例

装饰模式在实际项目中有很多应用场景,例如日志记录、权限验证和性能监控等。

日志记录功能的装饰

通过装饰器为组件添加日志记录功能,可以避免在每个组件中重复写日志代码:

class LoggingDecorator extends Decorator {
    public LoggingDecorator(Component component) {
        super(component);
    }

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

public class LoggingExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component loggingComponent = new LoggingDecorator(component);
        loggingComponent.operation();
    }
}
权限验证功能的装饰

通过装饰器为组件添加权限验证功能,可以在调用实际业务逻辑之前进行权限检查:

class PermissionDecorator extends Decorator {
    public PermissionDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        if (hasPermission()) {
            super.operation();
        } else {
            System.out.println("Access denied");
        }
    }

    private boolean hasPermission() {
        // 模拟权限验证逻辑
        return true; // 可以根据实际情况修改
    }
}

public class PermissionExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component permissionComponent = new PermissionDecorator(component);
        permissionComponent.operation();
    }
}
性能监控功能的装饰

通过装饰器为组件添加性能监控功能,可以方便地记录组件的执行时间:

class TimingDecorator extends Decorator {
    public TimingDecorator(Component component) {
        super(component);
    }

    @Override
    public void operation() {
        long startTime = System.currentTimeMillis();
        super.operation();
        long endTime = System.currentTimeMillis();
        System.out.println("Operation took " + (endTime - startTime) + " milliseconds");
    }
}

public class TimingExample {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();
        Component timingComponent = new TimingDecorator(component);
        timingComponent.operation();
    }
}

装饰模式的优缺点

优点
  1. 单一职责原则:可以将职责划分到不同的类中,使每个类的功能更加单一和明确;
  2. 动态扩展功能:可以在运行时添加或删除功能,而无需修改原有代码;
  3. 灵活性高:通过不同的装饰器组合,可以实现多种不同的功能扩展;
  4. 减少代码重复:可以避免在多个类中重复实现相同的功能,减少代码冗余。
缺点
  1. 增加复杂性:装饰器的嵌套使用可能会导致代码结构复杂,不易理解和维护;
  2. 调试困难:由于装饰器改变了函数的行为,调试时可能不容易追踪到问题的根源;
  3. 性能开销:多层装饰器可能会增加函数调用的开销,影响性能。

应用场景

装饰模式适用于以下场景:

  1. 需要动态添加功能:例如为已有功能添加日志记录、性能监控或权限验证等;
  2. 功能扩展频繁:例如在项目中需要经常为不同对象添加或移除功能;
  3. 不希望修改原有代码:例如在使用第三方库时,不希望直接修改其源代码,而是通过装饰器来扩展其功能;
  4. 跨切面关注点:例如在面向切面编程中,装饰模式可以用于处理日志、事务管理、异常处理等横切关注点。

总结

通过这篇文章,希望读者能够更好地理解装饰模式在Java中的实现,并能够在实际开发中灵活应用这种设计模式。如果你有任何疑问或想法,欢迎在下方留言!别忘了关注我们的公众号,获取更多有趣的编程知识和实用的代码技巧,我们期待与你的交流与分享!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1962315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JavaSE-线程安全问题-死锁详解】

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 🌈…

HTML基础1-文本级元素

HTML 简介 什么是 HTML? HTML (HyperText Markup Language) 是一种用于创建网页的标准标记语言。它通过使用一系列预定义的元素来描述文档的结构和外观, 您可以使用 HTML 来建立自己的 WEB 站点。 HTML 的作用 HTML 用于定义网页的结构,…

快手文生图模型-Kolors快速上手

Kolors是什么 可图(Kolors):用于真实感文本到图像合成的扩散模型的有效训练 可图,是快手开源的一个文生图模型,架构上使用了chatglm,比普通的sd模型在中文理解上要强大很多,以往sd模型的提示词理解能力往往只有两种 …

《BeanShell 在 JMeter 中的应用》总结

通过案例进行讲解 一、BeanShell 介绍 官网: http://www.BeanShell.org BeanShell 是一种完全符合 Java 语法规范的脚本语言,具有以下特点: 是一种松散类型的脚本语言,类似 JS。是用 Java 写成的小型、免费、可下载的嵌入式 Java 源代码解…

计算机毕业设计选题推荐-零食批发商仓库管理系统-Java/Python项目实战

✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

LocalDateTime的序列化和反序列化

背景 最近定位出一个LocalDateTime序列化相关的问题,简单记录一下。本文重点介绍Jackson对LocalDateTime的序列化和反序列化,并结合Spring应用场景进行介绍。 1.LocalDateTime与字符串转换 可以通过DateTimeFormatter实现LocalDateTime与字符串的相互…

Windows远程桌面无法拷贝文件问题

场景说明 Winwdows远程桌面,相比Linux方便一点就是,同是windows连接,其中复制粘贴功能,可以在两个windows无缝切换。 但最近笔者远程一台测试windows服务器时,发现无法在服务器上复制内容到本地,也无法从…

西门子s7第三方(S7netplus)读写操作

和西门子PLC通讯需要使用S7netplus​​这个包,可以在NuGet​​上搜索下载,下载后引入命令空间using S7.Net;​​ 创建PLC对象进行连接使用Write Read进行读写操作即可不需要在发请求帧 //创建Plc对象Plc plc; //西门子设备是s7-1200//参数1 CPu类型//参…

微信小程序+JAVA实现微信支付

时隔两年再次回归 本文主要讲的是小程序实现微信支付功能,后台采用JAVA。 一.准备工作 1.小程序 2.微信商户号 1.商户号申请 这里对小程序的申请不做赘述。 如果没有微信商户号的同学,点击该链接https://pay.weixin.qq.com/,按照下属步骤…

低代码与人工智能的融合:加速应用开发的未来趋势

什么是低代码,它是如何工作的? 低代码是一种软件开发概念,它通过最小化手工编码的方式,为开发和部署定制化应用提速。低代码平台具备模型驱动、沙盒多环境、可编程的可视化开发方式等,能用于开发包含有用户界面、业务逻…

二叉树——链式结构的实现

首先是分为三个文件进行实现:tree.h、tree.c、test.c tree.h 用链表来表示⼀棵⼆叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩⼦和右孩⼦所在…

基于Springboot + vue + mysql 校友社交管理系统 设计实现

目录 📚 前言 📑摘要 1.1 研究背景 📑操作流程 📚 系统架构设计 📚 数据库设计 💬 E-R表 4.2.2数据库逻辑结构设计 📚 系统功能的具体实现 系统功能模块 系统首页 校友会信息 校友活动 …

仿RabbitMQ实现消息队列———整体框架

目录 一、项目简介 需求分析 AMQP 特点: AMQP 模型: 交换机类型 持久化 网络通信 二、服务端模块 1、交换机数据管理 2、队列数据管理 3、绑定数据管理 4、消息数据管理 5、虚拟机数据管理 6、路由匹配管理 7、消费者管理 8、信道管理 …

智源发布三款BGE新模型,再次刷新向量检索最佳水平

近期,以大语言模型(LLM)为基础的向量模型(embedding model)变得愈发流行。得益于大语言模型强大的语义理解能力,相关模型在下游任务中的检索精度得到了显著的提升。然而,当前基于大模型的向量模…

leetcode 1555 银行账号概要(postgresql)

需求 用户表: Users --------------------- | Column Name | Type | --------------------- | user_id | int | | user_name | varchar | | credit | int | --------------------- user_id 是这个表的主键。 表中的每一列包含每一个用户当前的额度信息。 交易表&…

Nginx反向代理实战

使用反向代理代理服务 假设我们有三台服务器提供不同的服务 nginx作为代理服务器 代理服务器: 192.168.101.23 其余三台服务器 服务器1 192.168.101.18 服务器2 192.168.101.87 服务器3 192.168.101.20 代理服务器的nginix配置 server {listen 8085;ser…

【机器学习基础】机器学习概述与实践基础

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科,通过算法和模型让计算机从数据中学习,进行模型训练和优化,做出预测、分类和决策支持。Python成为机器学习的首选语言,…

Docker中使用自定义网络方式实现Redis集群部署与测试流程

场景 Docker中Docker网络-理解Docker0与自定义网络的使用示例: Docker中Docker网络-理解Docker0与自定义网络的使用示例-CSDN博客 参考上面的流程实现自定义网络的实现。 下面记录其应用实例,使用Docker的自定义网络实现redis集群部署。 注&#xf…

IP地址https证书的优势与申请途径

一、IP地址SSL证书的优势 无需域名:对于一些内部系统或者专用设备而言,它们可能不具有域名,但仍需保障通信安全。IP地址SSL证书正好满足这一需求。简化管理:对于拥有大量设备的企业来说,维护每个设备的域名可能是一个…