重构代码之将双向关联改为单向关联

news2024/11/25 16:14:26

在代码重构中,双向关联改为单向关联是指将原本双向关联转变为单向关联。这种重构方式有助于简化对象模型和提高代码的可维护性,减少不必要的耦合。下面是对这个重构技巧的详细讲解。

一、为什么需要将双向关联改为单向关联?

  1. 减少耦合
    • 双向关联意味着类之间存在强耦合,这可能导致代码修改困难。一个类的改变可能会影响到另一个类,增加了维护的复杂性。
    • 将双向关联转为单向关联有助于减少类之间的相互依赖,增强代码的模块性,降低维护成本。
  2. 简化对象图
    • 双向关联会导致对象图更加复杂,特别是在持久化(如数据库映射)时。如果关联关系不对称,可能需要在持久化时额外的逻辑来保持一致性。
    • 单向关联能够简化对象图,避免不必要的复杂性。
  3. 避免循环引用
    • 双向关联可能引入循环引用,这会导致内存泄漏(特别是在垃圾回收的环境中)。
    • 单向关联可以避免这种情况,因为一个对象仅依赖于另一个对象,而没有反向依赖。

二、何时使用将双向关联改为单向关联重构

  • 不需要反向访问时:如果反向访问并不重要,或者从性能角度看没有必要,那么可以将关联关系改为单向关联。
  • 数据库建模时:在关系数据库中,双向关联常常是多余的,特别是在 ORM 框架(如 Entity Framework)中,过多的双向关联可能导致不必要的表连接和性能问题。
  • 避免复杂性:如果双向关联导致代码理解或测试的复杂性增加,可以考虑使用单向关联来简化设计。

三、如何进行重构

  1. 移除反向引用
    • 例如,如果 A 类有一个指向 B 类的引用,同时 B 类也有一个指向 A 类的引用,那么可以将 B 类中的引用去掉,只保留 A 类对 B 类的引用。
  2. 调整业务逻辑
    • 如果去掉反向引用,可能需要调整业务逻辑,确保仍然能够满足需求。比如,访问 B 的时候可能需要通过某些外部手段来获取反向关系。
  3. 修改数据库模型(如果适用)
    • 如果你在使用 ORM 框架(如 Entity Framework),你需要修改数据库模型和映射,删除多余的外键关系或导航属性。
  4. 调整代码中的访问方式
    • 确保代码的其他部分也能够适应这种改动。例如,在 A 类中可以通过调用 B 类的方法或属性来处理与 B 的交互,而不再依赖于反向引用。

四、示例

假设有两个类 AuthorBookAuthor 类和 Book 类之间有双向关联:每个 Author 可以有多个 Book,而每个 Book 也可以知道自己所属的 Author

4.1 原始代码(双向关联):
public class Author
{
    public string Name { get; set; }
    public List<Book> Books { get; set; }

    public Author()
    {
        Books = new List<Book>();
    }
}

public class Book
{
    public string Title { get; set; }
    public Author Author { get; set; }
}

在这种情况下,Author 类通过 Books 属性知道所有相关的 Book 对象,而 Book 类也通过 Author 属性知道其所属的 Author

4.2 重构后的代码(单向关联):
public class Author
{
    public string Name { get; set; }
    public List<Book> Books { get; set; }

    public Author()
    {
        Books = new List<Book>();
    }
}

public class Book
{
    public string Title { get; set; }
    // 移除了 Author 属性
}

在这个例子中,Book 类不再直接持有对 Author 的引用,从而减少了类之间的耦合。这种重构简化了模型,减少了不必要的复杂性。

五、总结

“Change Bidirectional Association to Unidirectional”重构技巧有助于降低类之间的耦合度,使代码更简洁、易于维护。在进行这种重构时,必须确保业务逻辑仍然能够正常运行,并避免引入不必要的复杂性。这种重构通常适用于对象间的关系不需要双向访问,或者在数据库建模时,双向关系并不必要。

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

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

相关文章

学Linux的第九天--磁盘管理

目录 一、磁盘简介 &#xff08;一&#xff09;、认知磁盘 &#xff08;1&#xff09;结构 &#xff08;2&#xff09;物理设备的命名规则 &#xff08;二&#xff09;、磁盘分区方式 MBR分区 MBR分区类型 扩展 GPT格式 lsblk命令 使用fdisk管理分区 使用gdisk管理分…

QT实现拷贝复制文件操作 QT5.12.3环境 C++实现

案例需求&#xff1a;利用QT线程操作&#xff0c;实现拷贝复制文件操作 代码&#xff1a; myfile.h #ifndef MYFILE_H #define MYFILE_H#include <QObject> #include <QDebug> #include <QThread> #include <QFile> #include <QtWidgets> class…

IDEA 2024安装指南(含安装包以及使用说明 cannot collect jvm options 问题 四)

汉化 setting 中选择插件 完成 安装出现问题 1.可能是因为之前下载过的idea&#xff0c;找到连接中 文件&#xff0c;卸载即可。

Jenkins-Git Parameter 插件实现指定版本的发布和回滚

在上一篇文章的基础设置上进行 1. 机器准备 开发10.0.0.204gitlab10.0.0.201jenkins10.0.0.200web10.0.0.202 2. 开发主机 在开发机器上修改不同版本的前端页面&#xff0c;并打上标签 第一次修改 [rootdev wheel]#vim index.html [rootdev wheel]#git commit -am "1…

Ubuntu ESP32开发环境搭建

文章目录 ESP32开发环境搭建安装ESP-IDF搭建一个最小工程现象 ESP32开发环境搭建 最近有个小项目需要用到能够联网的mcu驱动&#xff0c;准备玩玩esp的芯片&#xff0c;记录下ESP32开发环境搭建的过程。 ESP-IDF 是乐鑫科技为其 ESP32 系列芯片提供的官方开发框架。这个框架主…

《剖析 Spring 原理:深入源码的旅程(二)》

六、Spring 的 Bean 注入与装配 Spring 的 Bean 注入与装配的方式有很多种&#xff0c;可以通过 xml、get set 方式、构造函数或者注解等。简单易用的方式就是使用 Spring 的注解&#xff0c;Spring 提供了大量的注解方式&#xff0c;如 Autowired、Qualifier 等。Spring 还支持…

Git的使用_仓库管理_CI/CD介绍

文章目录 一、Git的基础知识一-1、什么是GitLinux命令行的git的简易安装Git项目的组成Git的基本工作流程Git文件的三种状态 一-2、存储库远程存储库与本地存储库创建存储库git init命令的使用方法1. 初始化一个新的 Git 仓库2. 在指定目录初始化一个新的 Git 仓库3. 初始化一个…

Android 实现悬浮球的功能

Android 实现悬浮球的功能 在 Android 中&#xff0c;实现悬浮球可以通过以下方式实现&#xff0c;常见的方法是使用 WindowManager 创建一个悬浮窗口。以下是具体的实现步骤&#xff1a; 1. 配置权限 在 AndroidManifest.xml 中添加悬浮窗权限&#xff1a; <uses-permis…

C语言数据结构学习:循环队列

C语言 数据结构学习 汇总入口&#xff1a; C语言数据结构学习&#xff1a;[汇总] 1. 循环队列 队列的博客&#xff1a;C语言数据结构学习&#xff1a;队列 循环队列会预先定义最大队列空间&#xff0c;然后定义一个数组&#xff0c;通过队列头和队列尾指针分别指向开头和结尾&…

Java教程:SE进阶【十万字详解】(下)

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

37_U-Net网络详解

1.U-Net 网络概述 U-Net 是一种深度学习模型&#xff0c;广泛用于图像的语义分割任务。U-Net 网络的结构特别适合医学影像分割&#xff0c;尤其在少量训练数据的情况下表现优异。该网络由一个编码器-解码器架构组成&#xff0c;具有对称的“U”形结构&#xff0c;因此得名为 U…

mysql-分析MVCC原理

一、MVCC简介 MVCC是一种用来解决读写冲读的无锁并发控制&#xff0c;也就是为事务分配单增长的时间戳&#xff0c;为每个修改保存一个版本&#xff0c;版本与事务时间戳关联&#xff0c;读操作只读该事务开始前的数据库的快照&#xff0c;所以MVCC可以为数据库解决一些问题。…

【CSP CCF记录】201812-2第15次认证 小明放学

题目 样例1输入 30 3 30 8 0 10 1 5 0 11 2 2 0 6 0 3 3 10 0 3 样例1输出 30 3 30 8 0 10 1 5 0 11 2 2 0 6 0 3 3 10 0 3 思路 参考&#xff1a;CCF小白刷题之路---201812-2 小明放学&#xff08;C/C 100分&#xff09;_小明放学测试数据-CSDN博客 我们使用一个for循环计算…

Kafka 分区分配及再平衡策略深度解析与消费者事务和数据积压的简单介绍

Kafka&#xff1a;分布式消息系统的核心原理与安装部署-CSDN博客 自定义 Kafka 脚本 kf-use.sh 的解析与功能与应用示例-CSDN博客 Kafka 生产者全面解析&#xff1a;从基础原理到高级实践-CSDN博客 Kafka 生产者优化与数据处理经验-CSDN博客 Kafka 工作流程解析&#xff1a…

计算机网络-VPN虚拟专用网络概述

前面我们学习了在企业内部的二层交换机网络、三层路由网络包括静态路由、OSPF、IS-IS、NAT等&#xff0c;现在开始学习下VPN&#xff08;Virtual Private Network&#xff0c;虚拟专用网络&#xff09;&#xff0c;其实VPN可能很多人听到第一反应就是梯子&#xff0c;但是其实这…

《第十部分》1.STM32之通信接口《精讲》之IIC通信---介绍

经过近一周的USART学习&#xff0c;我深刻体会到通信对单片机的重要性。它就像人类的手脚和大脑&#xff0c;只有掌握了通信技术&#xff0c;单片机才能与外界交互&#xff0c;展现出丰富多彩的功能&#xff0c;变得更加强大和实用。 单片机最基础的“语言”是二进制。可惜&am…

【蓝桥杯C/C++】深入解析I/O高效性能优化:std::ios::sync_with_stdio(false)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 蓝桥杯C/C 文章目录 &#x1f4af;前言&#x1f4af;C 语言与 C 语言的输入输出对比1.1 C 语言的输入输出1.2 C 语言的输入输出 &#x1f4af; std::ios::sync_with_stdio(false) 的作用与意义2.1 什么是 std::ios::s…

初识Linux—— 基本指令(下)

前言&#xff1a; 本篇继续来学习Linux的基础指令&#xff0c;继续加油&#xff01;&#xff01;&#xff01; 本篇文章对于图片即内容详解&#xff0c;已同步到本人gitee&#xff1a;Linux学习: Linux学习与知识讲解 Linux指令 1、查看文件内容的指令 cat ​ cat 查看文件…

VM虚拟机装MAC后无法联网,如何解决?

✨在vm虚拟机上&#xff0c;给虚拟机MacOS设置网络适配器。选择NAT模式用于共享主机的IP地址 ✨在MacOS设置中设置网络 以太网 使用DHCP ✨回到本地电脑上&#xff0c;打开 服务&#xff0c;找到VMware DHCP和VMware NAT&#xff0c;把这两个服务打开&#xff0c;专一般问题就…

MCGSMCGS昆仑通态触摸屏

MCGS昆仑通态触摸屏应用实例详解 1目录设置 本案例讲了两个窗口的互相调用 创建工程 首先创建一个新工程 打开软件 McgsPro组态软件 菜单栏&#xff1a;文件&#xff1a;新建工程 打开工程设置窗口 HMI配置中应该是对应的不同型号的触摸屏&#xff0c; 选择一个类型&#x…