业务代码中如何使用装饰器模式?

news2024/9/22 15:25:47

装饰器模式(Decorator Pattern)介绍

装饰器模式(Decorator Pattern)是一种结构型设计模式,我们可以动态地给一个对象添加额外的职责。而不是通过继承增加子类的方式来扩展对象的功能,装饰器模式使用组合的方式来增强对象的功能,这有助于保持类的职责单一,提高了类的复用性和灵活性。

装饰器模式通常涉及以下角色:

  • • 组件(Component)接口:定义了一个对象接口,可以动态地给这些对象添加职责。

  • • 具体组件(Concrete Component):实现了组件接口的对象,这是我们要动态添加职责的对象。

  • • 装饰器(Decorator)类:实现了组件接口的抽象类,并持有一个组件接口的引用。这个类的任务是定义那些可以动态添加的职责。

  • • 具体装饰器(Concrete Decorator):实现了装饰器类的具体类,负责给组件添加新的职责。

优缺点

优点:

  • • 扩展对象功能:装饰器模式提供了一种灵活的替代方案来扩展对象的功能,比继承更灵活。

  • • 动态添加职责:可以动态地添加或删除对象的职责。

  • • 复合而非继承:通过使用组合而非继承的方式,避免了在层级关系上造成静态的继承关系,提高了代码的可复用性和灵活性。

缺点:

  • 增加系统复杂性:使用大量的小类,可能会增加系统的复杂度。

  • 多层装饰比较复杂:当装饰链过长时,会增加系统的复杂度,并且调试时可能会带来不便。

Spring Boot中业务代码示例

假设我们有个下单流程计算价格,现在我们需要新增一个打折优惠。怎么不修改原来代码巧妙的增加我们的功能呢?通过装饰器模式将不同的折扣策略作为装饰层动态添加到订单处理流程中。这样,我们可以在不修改现有类的情况下,灵活地添加或修改折扣策略。

订单接口

首先,定义一个订单服务接口,这是我们的组件接口:

public interface OrderService {
    double applyDiscount(double orderTotal);
}

实现一个基本的订单服务:

@Component
public class SimpleOrderService implements OrderService {
    @Override
    public double applyDiscount(double orderTotal) {
        // 默认情况下,没有任何折扣
        return orderTotal;
    }
}

装饰器实现

接着,我们创建一个装饰器抽象类:

@Component
public abstract class OrderServiceDecorator implements OrderService {
    @Resource
    protected OrderService simpleOrderService;

    @Override
    public double applyDiscount(double orderTotal) {
        return simpleOrderService.applyDiscount(orderTotal);
    }
}

定义不同的折扣策略作为装饰器:

@Component
public class PercentageDiscountDecorator extends OrderServiceDecorator {

    @Override
    public double applyDiscount(double orderTotal) {
        // 折扣率
        double discountRate = 0.2;
        double discount = orderTotal * discountRate;
        return super.applyDiscount(orderTotal - discount);
    }
}

整体结构如下

图片

测试一下

@SpringBootApplication
public class DecoratorPatternApplication {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DecoratorPatternApplication.class, args);

        OrderService percentageService = context.getBean(PercentageDiscountDecorator.class);

        double orderTotal = 300.0;
        double discountedTotal = percentageService.applyDiscount(orderTotal);
        System.out.println("Discounted order total: " + discountedTotal);
    }
}

图片

在这个例子中,通过PercentageDiscountDecorator 添加了百分比折扣。通过这种方式,我们可以根据需要灵活地组合和应用不同的折扣策略,而不必更改现有的订单服务代码。这种方法提高了代码的可维护性和扩展性,同时也保持了业务逻辑的清晰性。

与策略模式区别

之前分享过策略模式的实现:如何在业务代码中优雅的使用策略模式

我们回顾下策略模式的特征:策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式让算法独立于使用它的客户端而变化,即分离了算法的定义和使用,客户端代码通过依赖注入的方式选择使用哪一种策略。

在我们上面的示例中,如果使用装饰器模式,我们可以动态地为订单服务添加额外的功能(如折扣),而每个装饰器都可以独立地添加额外的职责。

而如果使用策略模式来处理折扣,我们可能会定义一个折扣策略接口,然后为每种折扣定义一个具体的策略类。客户端代码决定使用哪一种折扣策略,并将其应用于订单总额上。这里,策略是静态选择的,并且一次只能应用一个策略。

装饰器模式强调的是如何动态地添加职责,而策略模式强调的是如何封装算法和行为,并在它们之间切换。

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

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

相关文章

Android14之编译输出system/product/vendor/odm分区(一百九十一)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

【数据结构】HashMap的实现与常见问题

目录 一、概念 哈希算法与哈希表 二、哈希碰撞与解决 解决哈希冲突的四种方法 HashMap解决哈希冲突 三、代码实现 四、HashMap面试题 两个对象的hashcode一样那么equals一定一样吗?&& 两个对象的equals一样那么hashcode一定一样吗? Hash…

灵敏度都那么低了,为什么CCA的阈值还是-82

实际这个值的确是可以变化的。只是一般都不怎么变。 主要决定于两个因素。一个因素是邻区的干扰。如果干扰弱,那么就可以调高一点。跟布网有关。那么其实在家庭环境,这个不好控制。所以CCA阈值不好调整。但是如果仔细测量邻区的干扰,依然是可…

宝塔linux部署react项目 图文并茂 傻瓜式教学

华为云服务器购买与宝塔linux系统安装 购买服务器过程省略,记得付款就好,或者新人可去白嫖一个月试用 linux服务器安装宝塔 宝塔官网 不同版本安装命令 系统安装脚本Centos安装脚本yum install -y wget && wget -O install.sh https://downlo…

Android Studio轮播图使用失败怎么办【已解决】

Android Studio轮播图使用失败怎么办 1.在gethub上面搜索轮播图 2.选择要使用的轮播图 3.查看该轮播图的配置方法 4.复制该依赖放入build.gradle中 5.重新构建 6.使用banner 发现没有报错了 7.参考网址 https://github.com/youth5201314/banner

ELK-介绍及Elasticsearch集群搭建

ELK是三个开源软件的缩写,分别为Elasticsearch、Logstash、kibana它们都是开源软件。后来新增了一个FileBeat,它是一个轻量及的日志收集处理工具,因为Logstash由java程序开发,比较消耗内存资源,后来将Logstash使用go语…

解决gpt无法发送对话的问题

问题描述 如图,今天登上去发现怎么无法发送消息 解决 可能是cookie问题,重新删除了就行了 cookie删除后,需要重新登录,主题色也重置为原来的白色了

Node.js与Webpack笔记(二)

上一篇:Node.js与Webpack笔记(一)-CSDN博客 Webpack模块打包工具 1.Webpack简介以及体验 webpack是一个静态模块打包工具,从入口构建依赖图,打包有关的模块,最后用于展示你的内容 静态模块:编写…

ky10 server 银河麒麟服务器主备搭建 (nginx+keepalived)

下载脚本代码 git clone https://gitcode.net/zengliguang/nginx_keepalived_ky10_x.git 进入脚本路径 更新脚本代码 更新完成 执行安装脚本 安装nginx离线编译安装依赖 解压nginx源码 检查环境 编译 nginx安装成功 安装keepalived keepalived安装成功

华为OD机试真题-测试用例执行计划

测试用例执行计划 题目描述: 某个产品当前迭代周期内有N个特性({F1,F2,...,FN})需要进行覆盖测试,每个特性都被评估了对应的优先级,特性使用其ID作为下标进行标识。 设计了M个测试用例({T1,T2,...,TM}),每个用例对应了一个覆盖特…

【Python刷题】环形链表

问题描述 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&a…

SwiftUI之CoreData详解(一)

coreData 是一种数据持久化的方案,是对SQLite的一种封装。一说到这种桌面化的数据库,我就无比的怀念Foxbase|Foxpro, 多好的数据库产品,被微软扼杀了,相当年教大学生妹子们国家二级数据库时都是手把手教的,呃~~~&#…

解决火狐浏览器访问地址受限制问题(This address is restricted)

问题如下图: This address is restrictedThis address uses a network port which is normally used for purposes other than Web browsing. Firefox has canceled the request for your protection. 此地址受到限制 此地址使用通常用于 Web 浏览以外的目的的网…

21.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-配置数据保存到文件

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 如果看不懂、不知道现在做的什么,那就跟着做完看效果 内容参考于: 易道云信息技术研究院VIP课 上一个内容:20.数据分析工具…

人才推荐 | 毕业于美国凯斯西储大学的博士,专业知识广泛

编辑 / 木子 审核 / 朝阳 伟骅英才 伟骅英才致力于以大数据、区块链、AI人工智能等前沿技术打造开放的人力资本生态,用科技解决职业领域问题,提升行业数字化服务水平,提供创新型的产业与人才一体化服务的人力资源解决方案和示范平台&#x…

前端使用Ant Design中的Modal框实现长按顶部拖动弹框需求

需求:需要Ant Design中的一个Modal弹框,并且可以让用户按住顶部实现拖动操作 实现:在Ant Design的Modal框的基础上,在title中添加一个onMouseDown去记录拖拽的坐标,然后将其赋值给Modal的style属性 代码部分&#xff…

没有面试邀约还在怪学历?帮助1万人通过面试的简历实战经验

很多人说自己明明投了很多公司的简历,但是都没有得到面试邀请的机会。自己工作履历挺好的,但是为什么投自己感兴趣公司的简历,都没有面试邀请的机会。反而是那些自己没有投递的公司,经常给自己打电话。 造成这些现象的主要原因&am…

解决白屏问题:让你的网站重焕生机

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Ubuntu上安装任意版本nodejs方法

在Ubuntu中安装指定版本的Node.js,可以使用Node Version Manager (NVM)。以下是安装步骤: 首先,安装NVM。在命令行中输入: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash 这个命令会下载并…

Maya人物建模

【MAYA人物建模】超详细讲解人物嘴巴、鼻子、眼睛、耳朵、头发、帽子等布线细节,零基础人物头部布线教程_哔哩哔哩_bilibili 原始图像凑合用,视屏中截图 图像导入过程技巧总结 前视图/右视图模式下导入图形 创建图层 锁定后可以避免图片位置的移动 前视…