java 语言写一个装饰器模式代码

装饰器模式(Decorator Pattern)允许你动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。下面是一个简单的 Java 装饰器模式的示例代码:

首先,我们定义一个接口 Component

public interface Component {
    void operation();
}

然后,我们创建一个实现了 Component 接口的 ConcreteComponent 类:

public class ConcreteComponent implements Component {
    @Override
    public void operation() {
        System.out.println("执行具体组件的操作");
    }
}

接下来,我们创建一个抽象装饰器类 Decorator,它同样实现了 Component 接口,并持有对 Component 对象的引用:

public abstract class Decorator implements Component {
    protected Component component;

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

    @Override
    public void operation() {
        if (component != null) {
            component.operation();
        }
    }
}

现在,我们可以创建具体的装饰器类,它们扩展了 Decorator 类并添加了额外的功能:

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

    @Override
    public void operation() {
        super.operation(); // 调用原始组件的操作
        addedFunctionA(); // 添加额外的功能A
    }

    private void addedFunctionA() {
        System.out.println("添加功能A");
    }
}

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

    @Override
    public void operation() {
        super.operation(); // 调用原始组件或之前装饰器的操作
        addedFunctionB(); // 添加额外的功能B
    }

    private void addedFunctionB() {
        System.out.println("添加功能B");
    }
}

最后,我们使用这些类来展示装饰器模式的工作方式:

public class DecoratorPatternDemo {
    public static void main(String[] args) {
        Component component = new ConcreteComponent();

        // 创建装饰器,并将具体组件作为参数传递
        Component decoratorA = new ConcreteDecoratorA(component);
        Component decoratorAB = new ConcreteDecoratorB(decoratorA);

        // 执行操作,将调用所有的功能,包括原始组件和装饰器添加的功能
        decoratorAB.operation();
    }
}

运行 DecoratorPatternDemomain 方法,你将看到如下输出:

执行具体组件的操作
添加功能A
添加功能B

这个示例展示了如何使用装饰器模式动态地给一个对象(这里是 ConcreteComponent)添加功能(ConcreteDecoratorAConcreteDecoratorB)。你可以通过创建更多的装饰器类来添加更多的功能,而无需修改原始组件的代码。


装饰器模式和生成器模式相比有什么优缺点呢

装饰器模式和生成器模式在软件设计中各有其优缺点,它们解决的问题和目的也有所不同。以下是它们之间的主要比较:

装饰器模式

优点:

  1. 更高的灵活性:装饰器模式可以在不修改原始类的情况下,动态地给对象添加新的功能或责任。这使得代码更加灵活,易于扩展。
  2. 开闭原则:装饰器模式符合开闭原则,即在不修改原有代码的基础上,增加新的功能。这有助于保持代码的稳定性和可维护性。
  3. 功能组合:通过不同的装饰器组合,可以创建出具有不同功能组合的对象,从而实现更多的功能组合和扩展。

缺点:

  1. 增加系统复杂性:使用装饰器模式可能会产生很多小对象,这些对象之间的区别在于它们如何相互连接,而不是它们的类或属性值。这可能会增加系统的复杂性。
  2. 易于出错:由于装饰器模式提供了更多的灵活性,因此也更容易出错。特别是当对象被多次装饰时,调试时寻找错误可能需要逐级排查,较为繁琐。

生成器模式

优点:

  1. 代码复用性:生成器模式允许使用相同的构建过程来创建不同的表示形式,从而提高了代码的复用性和灵活性。
  2. 松散耦合:生成器模式可以将产品构建和产品表现分离,实现松散的耦合关系。这使得系统更加易于扩展和维护。

缺点:

  1. 设计复杂性:生成器模式需要设计复杂的构建算法和构建器类,这可能会增加系统的设计复杂性。
  2. 可能的过度使用:如果不恰当地使用生成器模式,可能会导致过度设计,使得系统变得复杂且难以维护。

总结

装饰器模式和生成器模式各有其优缺点,适用于不同的场景。装饰器模式主要用于在不修改原始类的情况下,动态地给对象添加新的功能或责任,适用于需要灵活扩展功能的场景。而生成器模式则主要用于使用相同的构建过程来创建不同的表示形式,提高代码的复用性和灵活性,适用于需要创建复杂对象并控制其构建过程的场景。在选择使用哪种模式时,需要根据具体的需求和场景来综合考虑。


在实际项目中,哪一种设计模式更常见呢

在实际项目中,装饰器模式和生成器模式的使用频率取决于项目的具体需求和上下文。然而,一般来说,装饰器模式在以下场景中更为常见:

  1. 动态功能扩展:当需要在运行时动态地给对象添加新功能或责任时,装饰器模式非常有用。例如,在GUI编程中,你可能需要动态地为按钮添加额外的行为(如禁用、高亮显示等),而不需要修改按钮的原始类。

  2. 责任链:装饰器模式可以很容易地实现责任链模式,其中每个装饰器都可以选择是否将请求传递给下一个装饰器或自己处理。这在处理具有多个可选步骤的流程时非常有用。

  3. 日志和审计:在需要记录对象操作的日志或进行审计的场景中,装饰器模式可以很容易地添加日志记录或审计功能,而无需修改原始对象的代码。

生成器模式在以下场景中更为常见:

  1. 复杂对象的构建:当需要构建复杂对象,并且这些对象的构建过程具有许多可选步骤或配置时,生成器模式非常有用。例如,在构建汽车时,你可以选择不同的引擎、颜色、轮胎等配置,生成器模式可以很容易地处理这些不同的配置选项。

  2. 构建顺序的控制:生成器模式允许你控制对象的构建顺序,确保在正确的时间点执行正确的操作。这在需要按照特定顺序执行多个步骤的场景中非常有用。

  3. 框架和库:在构建框架或库时,生成器模式可以提供一个灵活的方式来创建不同类型的对象,而无需在框架或库中硬编码这些对象的创建逻辑。

需要注意的是,虽然装饰器模式和生成器模式在某些方面有所重叠(例如,它们都可以用于创建具有不同配置的对象),但它们的侧重点和用途是不同的。因此,在选择使用哪种模式时,应该根据项目的具体需求和上下文来综合考虑。

此外,在实际项目中,许多设计模式可能会一起使用,以构建出更加健壮、灵活和可维护的代码库。因此,了解并熟悉多种设计模式是非常重要的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计划订单转采购申请的增强点和可以增强的内容

MD15 MD14 计划订单转采购申请,涉及的增强点和增强内容 对于外协的采购申请,有时候需要对组件的内容做一些特殊的处理,但是处理组件清单的增强ME_COMPONENTS_UPDATE的增强点(这个增强点对于手工创建的外协PR、外协PO,外协pr转外协…

Day21 代码随想录打卡|字符串篇---右旋转字符串

题目(卡码网 T55): 字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转…

Pycharm无法链接服务器环境(host is unresponsived)

困扰了很久的一个问题,一开始是在服务器ubuntu20.04上安装pycharm community,直接运行服务器上的pycharm community就识别不了anaconda中的环境 后来改用pycharm professional也无法远程连接上服务器的环境,识别不了服务器上的环境&#xff…

[力扣题解]102.二叉树的层序遍历

题目&#xff1a;102. 二叉树的层序遍历 代码 迭代法 class Solution { public:vector<vector<int>> levelOrder(TreeNode* root) {queue<TreeNode*> que;TreeNode* cur;int i, size;vector<vector<int>> result;if(root ! NULL){que.push(ro…

Pycharm导入自定义模块报红

文章目录 Pycharm导入自定义模块报红1.问题描述2.解决办法 Pycharm导入自定义模块报红 1.问题描述 Pycharm 导入自定义模块报红&#xff0c;出现红色下划线。 2.解决办法 打开【File】->【Setting】->【Build,Execution,Deployment】->【Console】->【Python Con…

【前端--Vue】组件之间的多种通信方式,一文彻底搞懂组件通信!

本篇将重点讲解vue中的多种组件通信方式&#xff0c;包括【父传子】【子传父】【兄弟组件通信】【依赖注入】等等&#xff0c;并提供具体案例来让小伙伴们加深理解、彻底掌握&#xff01;喜欢的小伙伴们点赞收藏&#xff0c;持续关注哦~&#x1f495; &#x1f49f; 上一篇文章…

【前端】HTML基础(2)

文章目录 前言一、HTML常见标签1、 注释标签1.1 标题标签1.2 段落标签1.3 换行标签 2、 格式化标签2.1 加粗标签2.2 倾斜标签2.3 删除线标签2.4 下划线标签 3、 图片标签3.1 src属性3.2 alt属性3.3 title属性3.4 图片大小3.5 图片边框 4、 超链接标签4.1 属性4.2 属性 前言 这篇…

爆赞好文之java反序列化之CB超详细易懂分析

java反序列化之CB超详细易懂分析 CB1环境搭建前言分析PropertyUtilsBeanComparatorPriorityQueue CB2环境搭建前言exp CB1 环境搭建 pom.xml <dependencies><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils&l…

QT:信号和槽

文章目录 信号和槽connect函数槽自定义槽第一种第二种 信号和槽 这里的信号和Linux的信号一样吗&#xff1f; 答案是差不多&#xff0c;但是也有一定的区别&#xff0c;而且也是两个不同的概念 信号有三个概念&#xff0c;一个是信号源&#xff0c;这个信号是由谁发送的&…

kafka学习笔记(三、生产者Producer使用及配置参数)

1.简介 1.1.producer介绍 生产者就是负责向kafka发送消息的应用程序。消息在通过send()方法发往broker的过程中&#xff0c;有可能需要经过拦截器(Interceptor)、序列化器(Serializer)和分区器(Partitioner)的一系列作用后才能被真正的发往broker。 demo: public class Kafk…

Ecovadis认证是什么?

Ecovadis认证是一种企业社会责任&#xff08;CSR&#xff09;评估和评级的认证&#xff0c;旨在衡量企业在环境、劳工和人权、道德以及可持续采购四个方面的可持续发展表现。该认证已成为全球范围内许多公司和组织的评估标准之一&#xff0c;有助于提高企业的会声誉和可持续发展…

LeetCode:滑动窗口最大值

文章收录于LeetCode专栏 LeetCode地址 滑动窗口最大值 题目 给你一个整数数组 nums&#xff0c;有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。   返回 滑动窗口中的最大值 。   示例 1…

浅谈操作系统中的重要概念——线程(3)——设计模式

文章目录 一、什么是设计模式&#xff1f;二、单例模式2.1、饿汉模式2.2、懒汉模式2.3、多线程情况下调用 饿汉模式与懒汉模式 谁是安全的&#xff1f;&#xff1f;&#xff08;重点&#xff09; 三、工厂模式 一、什么是设计模式&#xff1f; 设计模式就相当于菜谱&#xff0…

呆滞物料规范管理了,问题就好办了

对于制造企业来说&#xff0c;库存是生存和发展的重要保障&#xff0c;过高的库存会占用企业大量的资金和管理成本&#xff0c;影响企业的正常生产&#xff0c;然而多数中小制造企业还在用人工干预管理&#xff0c;如何控制呆滞物料成为仓储管理的一大难题。 什么是呆滞料 呆滞…

基于Spring Boot的家具网站设计与实现

基于Spring Boot的家具网站设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统前台主界面图&#xff0c;用户可进入家具网站可查看…

裸辞、裁员、老板跑路、被迫失业,未来是「超级个体」的时代

本期我们邀请的程序员是张立强&#xff0c;裸辞、裁员、老板跑路、被迫失业&#xff0c;管理层利益争夺&#xff0c;职业转型&#xff0c;工作五年&#xff0c;攒出了十年经验。程序员如何寻找自己的第二曲线&#xff0c;不妨听听立强的看法。 裸辞失业 大家好&#xff0c;我…

纯血鸿蒙APP实战开发——手写绘制及保存图片

介绍 本示例使用drawing库的Pen和Path结合NodeContainer组件实现手写绘制功能。手写板上完成绘制后&#xff0c;通过调用image库的packToFile和packing接口将手写板的绘制内容保存为图片&#xff0c;并将图片文件保存在应用沙箱路径中。 效果图预览 使用说明 在虚线区域手写…

使用Matplotlib库绘制了一个图形

前言 本文学习的用Matplotlib绘制一个正弦函数曲线&#xff0c;大家跟我来 第一步&#xff1a;编辑代码 import numpy as np import matplotlib.pyplot as plt xnp.linspace(0,10,1000) #用NumPy中的linspace函数生成一个包含1000个在0到10之间均匀分布的数值的数组&#xf…

瑞友天翼应用虚拟化系统SQL注入致远程代码执行漏洞复现

0x01 产品简介 瑞友天翼应用虚拟化系统是西安瑞友信息技术资讯有限公司研发的具有自主知识产权,基于服务器计算架构的应用虚拟化平台。它将用户各种应用软件集中部署在瑞友天翼服务器(群)上,客户端通过WEB即可快速安全的访问经服务器上授权的应用软件,实现集中应用、远程接…

网络基础(1)详解

目录 1.计算机网络背景 2.网络协议 3.网络中的地址管理 1.计算机网络背景 1.1 网络发展 (1)计算机从独立模式到网络互联(多态计算机连接共享数据)再到局域网LAN(通过交换机和路由器连接)接着是广域网WAN 1.2 协议 协议就是双方的一种约定. 为什么要有协议? 因为在数据长距…
最新文章