首页 > 编程语言 >装饰大师——装饰模式(Java实现)

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

时间:2024-07-31 09:25:26浏览次数:10  
标签:Java Component void component 装饰 operation public 大师

引言

大家好,上期我们介绍了装饰模式在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中的实现,并能够在实际开发中灵活应用这种设计模式。如果你有任何疑问或想法,欢迎在下方留言!别忘了关注我们的公众号,获取更多有趣的编程知识和实用的代码技巧,我们期待与你的交流与分享!
在这里插入图片描述

标签:Java,Component,void,component,装饰,operation,public,大师
From: https://blog.csdn.net/Asunqingwen/article/details/140813729

相关文章

  • Java编译和运行的命令
    在Java中,编译和运行Java程序主要使用两个命令:javac用于编译Java源代码,java用于运行编译后的Java字节码。编译Java程序要使用javac命令编译Java程序,你需要在命令行(终端或命令提示符)中导航到包含你的Java源代码文件的目录。然后,运行以下命令:bash复制代码javacYourProgram.ja......
  • Java跨平台原理
    Java源代码编译成字节码编译过程:Java源代码(.java文件)首先被Java编译器(javac)编译成一种中间代码,即字节码(.class文件)。这种字节码是一种与具体平台无关的代码,它可以在任何安装了Java虚拟机(JVM)的平台上被解释执行。字节码特性:字节码是Java实现跨平台的关键。它是一种介于源代码和......
  • 具有自引用的类装饰器的 Python 类型提示
    我的最终目标是编写一个系统来轻松记录函数调用(特别是类方法)。我首先编写一个带有包装方法的类Loggable,该方法允许我装饰子类方法并记录它们的调用|||现在我可以编写子类并记录它们的调用:Param=ParamSpec("Param")RetType=TypeVar("RetType")CountType=......
  • Java多态----继承
    一、基本概念关键字:extends    在java中,一个类(类A)继承另一个类(类B)是指类A能够直接使用类B的所有非构造方法和所有非私有属性(注意:不是不能使用是不能直接使用),并在类B原有的基础上继续进行扩充和延伸,即关键字extends的含义。通常,我们称类A与类B的关系为继承关系,继承方(......
  • Java多态----重写
    一、重写与重载    在学习重写之前,我们需要将它和重载进行区分:方法的重载,发生在同一个类中,方法名相同,参数列表不同,返回值无关。可参考上一篇文章中一个类中不同的构造方法,其也属于重载。详情可见于Java多态----继承-CSDN博客-------------------------------------......
  • Java的基础05(类型转换)
    类型转换   概念由于java是强类型语言,所以在进行有些运算时需要用到类型转换;低——————————>高byte,short,char--->int--->long(64)--->float(32)--->double(小数的优先级一定大于整数)运算中,不同类型的数据先转化为同一类型,然后进行运算;强制类型转换;自动类型......
  • Java基础入门(第一章)
    1Java是什么:Java是一门非常优秀的计算机编程语言Java英文翻译为印尼爪哇岛,地名,因盛产咖啡而闻名,漫漫长夜、唯有咖啡陪伴程序员1991年诞生,最初叫Oak(橡树),1995年改名为Java,2000年前后,成为世界上最流行的编程语言,过去二十多年中首屈一指。语言,人与人交流沟通的表达方式。......
  • Java项目开发中使用BigDecimal实例及注意事项补充
    去年写过一篇博客记录了日常项目开发中使用BigDecimal遇到的问题和注意事项:Java项目日常开发中使用BigDecimal常见问题总结今年在项目开发中遇到了几个实例,这里补充记录下。BigDecimal初始化时入参使用String类型,如果不是数字会抛异常NumberFormatException//java.lang.Nu......
  • 小白必看的java完整下载攻略!(在Typora中有图片参考)
    Java下载在浏览器上搜索JDK(2024年最新版是22,本人下载的是21)点击官网下载,会跳到Oracle官网,需要注册账号才可下载根据自己的电脑型号选择下载(本人下载的是64的)正常情况下下载的JDK版本后缀是exeJava安装的后续操作作为一个程序员坚持不懈才能成就大事。完成Java安装后事情还......
  • JavaScript 对象
    1.JavaScript对象把一个单一值(porsche)赋给名为car的变量varcar="porsche";对象也是变量。但是对象包含很多值。这段代码把多个值(porsche,911,white)赋给名为car的变量varcar={type:"porsche",model:"911",color:"white"};值以名称:值对的方式来书写(名称和......