当前位置: 首页 > news >正文

面向对象(精髓)变继承关系为组和关系(_Decorator模式)

在这里插入图片描述

在软件开发中,设计模式是解决常见问题的可重用解决方案。在面向对象编程中,继承和组合是两种常用的代码复用方式。然而,随着软件需求的不断变化,我们需要更灵活的设计方式来应对不断变化的需求。在本文中,我们将讨论从继承到组合的演进之路,并探讨如何通过组合设计模式来解决问题。

假如:要实现同时记日志和事务提交如何做比较好

不推荐写法(继承关系)

继承设计的缺陷在于它限制了代码的扩展性和灵活性。具体来说,它导致了以下问题:
在上面的 UML 图中,我们展示了使用继承关系实现日志记录和事务管理的示例。在这个示例中,我们有一个抽象类 LoggingRunnableTransactionalRunnable,它们都包含了一个抽象方法 doRun() 来执行具体的任务。然后,我们有一个具体的类 CodingTask,它继承自 LoggingRunnableTransactionalRunnable,并实现了 doRun() 方法来执行编码任务。

现在,假设我们需要修改系统,让每个编码任务先记录日志,然后再进行事务管理。使用继承关系,我们需要在现有的类结构中进行大量的修改,这可能会导致代码变得复杂和难以维护。下面是一个示例代码,展示了在现有系统中添加事务管理的改动:

public abstract class LoggingTransactionalRunnable extends LoggingRunnable {private final Runnable innerRunnable;public LoggingTransactionalRunnable(Runnable innerRunnable) {this.innerRunnable = innerRunnable;}@Overridepublic void run() {super.run();beginTransaction();innerRunnable.run();commitTransaction();}private void beginTransaction() {// 开启事务}private void commitTransaction() {// 提交事务}
}

在这个示例中,我们创建了一个新的抽象类 LoggingTransactionalRunnable,它继承自 LoggingRunnable,并实现了事务管理的功能。然后,我们修改了 CodingTask 类,使其继承自 LoggingTransactionalRunnable,以实现先记录日志,然后执行编码任务,最后进行事务管理的功能。

尽管这种方法可以实现需求,但它会导致现有系统的大量修改,可能会破坏现有的代码结构,增加代码的复杂性和难以维护性。因此,使用继承关系来实现这种需求存在 类耦合度高单一继承限制难以复用和测试可能不是最佳选择。

相对于继承关系,组合关系具有更低的耦合度和更高的灵活性。通过组合关系,可以将不同的功能模块化,并在运行时动态地组合它们,从而实现更灵活和可扩展的设计。因此,在设计类和对象时,应尽量避免过度使用继承关系,而是倾向于使用组合关系来实现代码的复用和扩展。

推荐写法(组合关系)

在这里插入图片描述
箭头表示实现关系和组合关系。其中 CodingTask、LoggingRunnable 和 TransactionalRunnable 类都实现了 Runnable 接口,表示它们都是可以在单独的线程中运行的任务。而 LoggingRunnable 和 TransactionalRunnable 类分别包含了一个 Runnable 类型的私有属性,表示它们与内部的任务对象发生了组合关系。
在这里插入图片描述

//LoggingRunnable.java
public class LoggingRunnable implements Runnable {private final Runnable runnable;public LoggingRunnable(Runnable innerRunnable) {this.runnable = innerRunnable;}@Overridepublic void run() {long startTime = System.currentTimeMillis();System.out.println("Task started at "+ startTime);//Decorator 模式是一种常见的设计模式,用于动态地为对象添加额外的功能,而不需要修改其原始类。runnable.run();System.out.println("Task finished. Elapsed time: "+ (System.currentTimeMillis() - startTime));}
}
// CodingTask.java
public class CodingTask implements Runnable {private final int employeeId;public CodingTask(int employeeId) {this.employeeId = employeeId;}@Overridepublic void run() {System.out.println("Employee " + employeeId+ " started writing code.");try {Thread.sleep(5000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("Employee " + employeeId+ " finished writing code.");}
}

上面的代码展示了使用组合关系实现的两个类:LoggingRunnableCodingTask

  1. LoggingRunnable 类:该类实现了 Runnable 接口,并包含了一个私有成员变量 runnable,类型为 Runnable 接口。在构造函数中,通过参数传入一个 Runnable 对象,然后在 run() 方法中,首先记录了任务开始的时间,然后调用传入的 Runnable 对象的 run() 方法执行具体的任务,最后记录了任务结束的时间。

  2. CodingTask 类:该类也实现了 Runnable 接口,表示一个编码任务。在 run() 方法中,它简单地打印出员工开始编写代码的消息,然后休眠 5 秒钟(模拟编写代码的过程),最后打印出员工编写代码完成的消息。

这两个类之间的关系是组合关系,即 LoggingRunnable 类包含一个 Runnable 接口的实例。通过这种组合关系,LoggingRunnable 类可以在执行任务前后添加额外的功能,而不需要修改 CodingTask 类的代码。这符合了开闭原则,即对扩展开放,对修改关闭。

功能扩展

如果有一天项目经理添加新需求事务和MQ 整合

对于组合设计模式,你可以想象一个新的扩展类,例如 MessagingTransactionalRunnable,它可以组合 TransactionalRunnableMessagingRunnable 两个功能,从而实现事务管理和向 MQ 发送消息的组合。下面是一个简单的示例:
在这里插入图片描述

public class MessagingTransactionalRunnable implements Runnable {private final Runnable innerRunnable;private final String message;public MessagingTransactionalRunnable(Runnable innerRunnable, String message) {this.innerRunnable = innerRunnable;this.message = message;}@Overridepublic void run() {try {beginTransaction();sendMessage(message);innerRunnable.run();commit();} catch (Exception e) {rollback();throw new RuntimeException(e);}}private void sendMessage(String message) {System.out.println("Sending message to MQ: " + message);// 实现向 MQ 发送消息的逻辑}private void commit() {System.out.println("Commit transaction");// 实现事务提交的逻辑}private void rollback() {System.out.println("Rollback transaction");// 实现事务回滚的逻辑}private void beginTransaction() {System.out.println("Begin transaction");// 实现事务开始的逻辑}
}

在这个示例中,MessagingTransactionalRunnable 类组合了 TransactionalRunnableMessagingRunnable 两个功能模块,通过调用它们的方法来实现事务管理和向 MQ 发送消息的组合。当 MessagingTransactionalRunnable 对象的 run 方法被调用时,它会先开始事务,然后发送消息到 MQ,执行内部的任务,最后提交或回滚事务。这样,你就可以很方便地使用组合设计模式来扩展功能了。

总结

继承的局限性

继承是面向对象编程中的一种重要概念,它允许子类继承父类的属性和方法。通过继承,可以实现代码的重用和扩展。然而,继承也存在一些局限性:

  • 耦合度高: 子类与父类之间存在紧密的耦合关系,子类的实现依赖于父类的具体实现细节。
  • 继承链过长: 当继承层次较深时,维护和理解代码变得困难,容易造成代码膨胀和复杂性增加。
  • 单一继承: 在单继承语言中,子类只能继承一个父类,限制了代码的灵活性和可复用性。

由于这些局限性,我们需要寻找一种更灵活的设计方式来解决问题。

组合的优势

组合是另一种常见的代码复用方式,它允许将对象组合在一起以实现新的功能。相比于继承,组合具有以下优势:

  • 低耦合度: 组合将对象之间的耦合度降低到最低限度,每个对象都可以独立存在并且可以被替换或重用。
  • 灵活性: 通过组合,可以动态地组合和重组对象以实现不同的功能,而不需要修改原始类的代码。
  • 多态性: 组合提倡面向接口编程,利用多态性来实现代码的灵活性和可扩展性。

扩展阅读

在这里插入图片描述

面向对象主题链接
类与对象链接
接口与抽象类链接
不可变性链接
变继承为组合(精髓一)状态模式链接
变继承为组合(精髓二)装饰器模式链接

相关文章:

面向对象(精髓)变继承关系为组和关系(_Decorator模式)

在软件开发中,设计模式是解决常见问题的可重用解决方案。在面向对象编程中,继承和组合是两种常用的代码复用方式。然而,随着软件需求的不断变化,我们需要更灵活的设计方式来应对不断变化的需求。在本文中,我们将讨论从…...

MES系统在智能生产中的重要作用

在未来智能制造的发展趋势中,制造执行系统(MES)作为关键技术和工具,扮演着至关重要的角色。随着科技的不断进步和制造业的数字化转型,MES的地位将愈发凸显,对于企业实现智能化生产、提高效率、降低成本具有…...

2024.3.13每日一题

LeetCode 最大二进制奇数 题目链接:2864. 最大二进制奇数 - 力扣(LeetCode) 题目描述 给你一个 二进制 字符串 s ,其中至少包含一个 1 。 你必须按某种方式 重新排列 字符串中的位,使得到的二进制数字是可以由该组…...

YOLOv5 | 涨点复现!YOLOv5添加BiFPN有效提升目标检测精度

目录 🚀🚀🚀订阅专栏,更新及时查看不迷路🚀🚀🚀 介绍: BiFPN 代码实现 ⭐欢迎大家订阅我的专栏一起学习⭐ 🚀🚀🚀订阅专栏,更新及…...

【Nut3】nuxt.config.ts项目nuxt配置文件介绍

简言 记录下nuxt3的nuxt.config.ts文件的介绍和使用。 Nuxt Configuration nuxt.config.ts Nuxt可以通过一个单独的nuxt.config文件进行简单配置。 配置文件创建 nuxt.config文件的扩展名可以是.js、.ts或.mjs。 然后默认导出全局函数defineNuxtConfig的返回值&#xff0c…...

区块链技术的革命性影响

1. 区块链技术的基本原理: 区块链是一种去中心化的分布式数据库技术,通过不断增长的记录(块)构成一个链式结构。每个区块包含了交易数据的加密信息以及上一个区块的哈希值,从而形成了不可篡改的交易记录。这种去中心化…...

多线程(volatile)

volatile的功能 保证内存可见性禁止指令重排序 内存可见性 简单的理解 两(多)个线程同时针对一个变量进行操作, 一个线程读, 一个线程修改, 此时读到的值不一定是修改过后的值 即读线程没有感知到变量的变化 (其实是 编译器/JVM 对于代码在多线程情况下的优化进行了误判) 从 J…...

蓝桥杯 填空 卡片

蓝桥杯 填空题 卡片 解题思路&#xff1a; 我们只需要消耗完卡片的个数即可。 代码示例&#xff1a; #include<bits/stdc.h> using namespace std; int a[10]; bool isEnd(){for(int i0;i<10;i){if(a[i]-1)return false;}return true; } bool getN(int x){while(x){i…...

ELK介绍使用

文章目录 一、ELK介绍二、Elasticsearch1. ElasticSearch简介&#xff1a;2. Elasticsearch核心概念3. Elasticsearch安装4. Elasticsearch基本操作1. 字段类型介绍2. 索引3. 映射4. 文档 5. Elasticsearch 复杂查询 三、LogStash1. LogStash简介2. LogStash安装 四、kibana1. …...

【UE5】非持枪状态蹲姿移动的动画混合空间

项目资源文末百度网盘自取 在BlendSpace文件夹中单击右键选择动画(Animation)中的混合空间(Blend Space) &#xff0c;选择SK_Female_Skeleton&#xff0c;命名为BS_NormalCrouch 打开BS_NormalCrouch 水平轴表示角色的方向&#xff0c;命名为Direction&#xff0c;方向的最…...

Windows C++ TCP开发(使用select函数以及设置非阻塞/Reuse属性)

1、select官方函数说明&#xff1a; 语法 C int WSAAPI select([in] int nfds,[in, out] fd_set *readfds,[in, out] fd_set *writefds,[in, out] fd_set *exceptfds,[in] const timeval *timeout );参数 [in] nfds 已忽略。 包含 nf…...

ARM TrustZone技术解析:构建嵌入式系统的安全扩展基石

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-LOdvohfCEnd8eKyd {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

初识Python语言-课堂练习【pyhton123题库】

初识Python语言-课堂练习【pyhton123题库】 一、单项选择题 1、Guido van Rossum正式对外发布Python版本的年份是&#xff1a; A 2008B 1998C 1991D 2002 【答案】C 【解析】暂无解析2、下面不是Python语言特点的是&#xff1a;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪…...

chrome高内存占用问题

chrome号称内存杀手不是盖的&#xff0c;不设设置的话&#xff0c;经常被它内存耗尽死机是常事。以下自用方法 1 自带的memory saver chrome://settings/performance PerformanceMemory Saver When on, Chromium frees up memory from inactive tabs. This gives active tab…...

【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件,fopen,fclose【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作篇-----程序文件和数据文件&#xff0c;文件的打开和关闭&#xff0c;二进制文件和文本文件【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 在了解完动态内存管…...

知识碎片收集

目录 1. 如何计算两点经纬度之间的距离2. 加权随机采样3.什么时LLDB和GDB 1. 如何计算两点经纬度之间的距离 1.知乎-如何计算两点经纬度间距离 2.根据两点经纬度坐标计算距离 3.根据经纬度计算两点之间的距离的公式推导过程以及google.maps的测距函数 4.根据经纬度点计算经…...

不可不知!用例图的绘制与应用全指南深度解析

在软件开发领域中&#xff0c;用例图是一种强大的工具&#xff0c;用于描述系统的功能需求以及系统与外部实体之间的交互。无论是在需求分析阶段还是在系统设计过程中&#xff0c;用例图都扮演着至关重要的角色。本文将全面介绍用例图的绘制方法和其在软件开发中的应用&#xf…...

【数据结构七】堆与PriorityQueue详解

堆 在Java中有一种数据结构基于队列&#xff0c;并保证操作的数据带有优先级&#xff0c;该数据结构应该提供了两个最基本的操作&#xff0c;一个是返回最高优先级对象&#xff0c;一个是添加新的对象。这种数据结构就是优先级队列(Priority Queue)。它的底层使用了堆这种数据结…...

uniapp写支付的操作

支付的时候一般需要几个参数&#xff1a; ‘timeStamp’: 时间戳,‘nonceStr’: 随机字符串&#xff0c;不超过32位‘package’: 下单后接口返回的prepauid‘signType’: 签名的算法‘paySign’: 后端会给前端一个签名sign: data.sign // 根据签名算法生成签名 <template&…...

微信小程序开发系列(二十四)·wxml语法·列表渲染·wx:for-item 和 wx:for-index

目录 1. 如果需要对默认的变量名和下标进行修改&#xff0c;可以使用wx:for-item 和 wx:for-index 2. 将 wx:for 用在 标签上&#xff0c;以渲染一个包含多个节点的结构块 方法一 方法二 3. 总结 3.1 wx:for-item 和 wx:for-index总结 3.2 总结 1. 如果需要对默…...

电子元器件失效分析与预防实战指南

1. 电子元器件失效的底层逻辑剖析 电子元器件失效的本质是材料特性、环境应力与时间因素共同作用的结果。作为一名硬件工程师&#xff0c;我处理过数百例元器件失效案例&#xff0c;发现失效模式往往遵循"应力-损伤-失效"的因果链。理解这个链条&#xff0c;才能从根…...

Mac开发者必备:OpenClaw联动千问3.5-27B实现代码审查自动化

Mac开发者必备&#xff1a;OpenClaw联动千问3.5-27B实现代码审查自动化 1. 为什么需要代码审查自动化&#xff1f; 作为独立开发者&#xff0c;我经常面临一个尴尬局面&#xff1a;在深夜提交代码后&#xff0c;第二天才发现引入了低级语法错误或潜在漏洞。传统CI工具虽然能捕…...

STM32电位器驱动库:轻量级ADC封装与中值滤波实现

1. 项目概述MentorBit-Potenciometro 是一款专为 MentorBit 系统设计的轻量级电位器&#xff08;Potentiometer&#xff09;模块驱动库&#xff0c;面向 STM32 平台&#xff08;典型为 STM32F4/F7/H7 系列&#xff09;的嵌入式固件开发。该库并非通用 ADC 抽象层&#xff0c;而…...

新手福音:通过快马生成图文并茂的ccswitch安装教程代码,轻松上手

最近在折腾一个叫ccswitch的工具&#xff0c;作为刚入门的新手&#xff0c;真的被各种环境配置搞得头大。好在发现了InsCode(快马)平台&#xff0c;它能直接生成带详细注释的安装教程代码&#xff0c;简直是救命稻草&#xff01;今天就把这个图文并茂的教程项目分享给大家。 c…...

第 1 章 Python 基础 知识点精讲

1.1 在交互式环境中输入表达式核心知识点Python 提供两种运行代码的方式&#xff1a;交互式环境&#xff08;IDLE / 终端&#xff09; 和 脚本文件&#xff08;.py&#xff09;。交互式环境&#xff1a;输入一行代码立即执行&#xff0c;适合快速测试、调试、学习语法启动方式&…...

告别截图贴图!用MATLAB的text函数+LaTeX,在图像任意位置添加公式注释(含α, β, ∑等符号)

科研图像标注革命&#xff1a;MATLABLaTeX实现动态公式嵌入全攻略 在学术论文与科研报告中&#xff0c;数据可视化图表的质量直接影响研究成果的呈现效果。传统方式中&#xff0c;研究者往往需要先导出图像&#xff0c;再通过第三方软件&#xff08;如Photoshop或PPT&#xff0…...

毫米波雷达数据处理避坑指南:AWR2243的complex1x与complex2x格式到底怎么选?

毫米波雷达数据格式深度解析&#xff1a;AWR2243的complex1x与complex2x实战选择策略 在毫米波雷达信号处理的实际工程中&#xff0c;ADC数据格式的选择往往被当作一个简单的配置参数&#xff0c;直到工程师们在后期信号处理阶段遇到难以解释的噪声问题或成像质量下降时&#x…...

第2篇:嵌入式芯片发展历程与全球主流厂商产品线全梳理

引言&#xff1a;嵌入式技术的诞生与电子产业智能化的发展关联 嵌入式技术的诞生与电子产业的智能化升级同频共振&#xff0c;是科技进步与产业需求深度融合的产物。自20世纪70年代第一块单片机问世以来&#xff0c;嵌入式芯片从最初简单的控制单元&#xff0c;逐步进化为支撑…...

面试官都爱问!Java并发编程18道灵魂拷问:从Synchronized到虚拟线程

文章目录开场&#xff1a;并发面试&#xff0c;一个让勇士变烈士的战场第一幕&#xff1a;基础篇——别小看Synchronized&#xff0c;水很深第1题&#xff1a;synchronized锁的底层原理是啥&#xff1f;Monitor又是啥玩意&#xff1f;第2题&#xff1a;synchronized和volatile到…...

Redacted Font:企业级产品设计的终极保密字体应用指南

Redacted Font&#xff1a;企业级产品设计的终极保密字体应用指南 【免费下载链接】redacted-font Keep your wireframes free of distracting Lorem Ipsum. 项目地址: https://gitcode.com/gh_mirrors/re/redacted-font Redacted Font是一款专为产品设计师和开发者设计…...