聊一聊代码重构——封装集合和替换算法的代码实践
代码重构相关内容
聊一聊代码重构——我们为什么要代码重构
聊一聊代码重构——代码中究竟存在哪些坏代码
聊一聊代码重构——关于变量的代码实践
聊一聊代码重构——关于循环逻辑的代码实践
聊一聊代码重构——关于条件表达式的代码实践
聊一聊代码重构——程序方法上的代码实践
聊一聊代码重构——程序方法和类上的代码实践
聊一聊代码重构——存在继承关系类上的代码实践
聊一聊代码重构——封装集合和替换算法的代码实践
封装集合
对集合属性进行封装
很多时候我们封装了对象属性的访问,这能提供属性的安全性,但是对于集合,我们一般会将集合作为一个整体来控制。这使得我们可以直接访问并修改集合,这使得集合变得脆弱。而很多时候我们更加在意的是集合内部的元素的操作,而不是对集合本身进行修改。所以在对象存在集合属性时,需要对集合进行特殊的封装。
需要那些封装
- 在getter方法中,返回集合的一个只读拷贝,以防止外部代码修改集合。
- 在setter方法中,进控制,将对集合的修改限制在元素上的修改。
- 对集合添加对集合元素内操作的方法。
就像下面对属性的封装
public class ShoppingCart {private List<Item> items = new ArrayList<>();public void addItem(Item item) {items.add(item);}public void removeItem(Item item) {items.remove(item);}public double getTotalPrice() {double total = 0;for (Item item : getItems()) {total += item.getPrice();}return total;}public List<Item> getItems() {return Collections.unmodifiableList(items);}private void setItems(List<Item> items) {this.items = items;}
}
在上面的示例中,我们将 items 属性设置为私有,并创建了 getter 和 setter 方法。我们在 setter 方法中添加了一些逻辑,以确保集合只能通过该方法进行修改。在 getter 方法中,我们返回集合的一个只读拷贝,以防止外部代码修改集合。在 getTotalPrice 方法中,我们通过 getItems 方法来访问集合。最终,我们可以逐步修改代码中所有直接访问 items 属性的地方,使其改为通过 getter 和 setter 方法进行访问。
替换算法
很多时候在最开始实现业务的时候对业务最终展现的形式不是很清晰,或者因为时间原因我们只能选择最快实现业务的方式。但是这些内容有可能并不是最好的方式,在原先的做法之外,可能存在更简单的解决方案,此时在重构代码时需要尝试对原来算法进行重构。比如使用更高效的算法替代低效算法,使用已经存在的三方库中方法替代自己编写的方法等。
如何进行算法替换
- 选择一个可以替换当前算法的新算法。
- 如果新的算法不是三方库中已有的内容,则将新算法实现为一个新的方法。
- 在原方法调用地方切换为新方法。
- 测试正确性,比较新算法的性能。
什么样的内容要替换算法
-
使用高效算法替换低效的算法
-
使用高可读性的算法替换低可读性算法
引入特例
特殊的逻辑
正常业务中,即使逻辑分支不同,但是其需要经历的流程大多是类似的,这个时候我们使用一些系列公共逻辑将其抽象。后来的开发同学在理解这些内容时会更加容易。但是某些时候,总会有某个特殊的逻辑分支在业务逻辑或者涉及数据范围都和其他分支差异巨大。为了不破坏原有代码结构和设计,又不想在父类中添加太多的特定逻辑。我们可以声明一个特殊标记的专门类来处理这个逻辑,需要处理这个逻辑的地方调用这个特例类的方法。这个特例类通常是一个继承自父类的子类,但是只包含特定的逻辑处理,不包含其他的业务逻辑。这样既完成了特殊处理,又保持原有的代码结构和设计,避免对原有代码的影响和破坏。但是,过度使用引入特例可能会导致代码过于复杂和难以维护,因此需要根据具体情况进行选择和使用。
下面情况下可以考虑使用引入特例的重构
-
如果业务分支中,存在大量针对特殊情况的判断和处理,并且这些特殊情况的处理逻辑相同。
-
特殊分支处理逻辑和正常情况的处理逻辑内容迥异,其逻辑会影响对正常逻辑的理解和扩展。
尝试引入特例的
- 审查代码,找出代码中符合上面描述的特殊情况。
- 创建一个特例类,该类应该继承自原来的类,并重写特殊情况下的方法。
- 在原来的类中添加一个方法,用于判断当前是否为特殊情况。
- 在原来的类中,将特殊情况下的代码替换为使用特例类的代码。如果当前为特殊情况,则创建特例类的实例并调用其方法,否则调用原来的方法。
- 测试
下面是一个使用特例方式重构的demo
原始代码中getTotalPrice(),当检测到特殊产品ID时候会使用与正常计算规则不同的计算方式。如果一个系统中是通过优惠标记来进行产品折扣的,那么这种固定产品ID进行折扣的方式,显然和产品正常涉及的逻辑不相符合。这个时候我们可以提供一个特殊的对象,将其内部处理逻辑和正常逻辑隔离出来
public class Order {private int productId;private int quantity;private double price;public Order(int productId, int quantity, double price) {this.productId = productId;this.quantity = quantity;this.price = price;}public double getTotalPrice() {if (productId == 1) {return quantity * price * 0.9;} else {return quantity * price;}}
}
在下面新建一个继承于新对象的SpecialPriceOrder,初始化时使用新的对象取代原始对象。将正常的代码逻辑和特殊的代码逻辑隔离出来
public class SpecialPriceOrder extends Order {public SpecialPriceOrder(int productId, int quantity, double price) {super(productId, quantity, price);}@Overridepublic double getTotalPrice() {return super.getTotalPrice() * 0.9;}
}public class Order {private int productId;private int quantity;private double price;public Order(int productId, int quantity, double price) {this.productId = productId;this.quantity = quantity;this.price = price;if (productId == 1) {this.setSpecialOrder(new SpecialPriceOrder(productId, quantity, price));}}......
}
相关文章:
聊一聊代码重构——封装集合和替换算法的代码实践
代码重构相关内容 聊一聊代码重构——我们为什么要代码重构 聊一聊代码重构——代码中究竟存在哪些坏代码 聊一聊代码重构——关于变量的代码实践 聊一聊代码重构——关于循环逻辑的代码实践 聊一聊代码重构——关于条件表达式的代码实践 聊一聊代码重构——程序方法上的…...
FPGA解码4K分辨率4line MIPI视频 OV13850采集 提供工程源码和技术支持
目录1、前言2、Xilinx官方主推的MIPI解码方案3、纯Vhdl方案解码MIPI4、vivado工程介绍5、上板调试验证6、福利:工程代码的获取1、前言 FPGA图像采集领域目前协议最复杂、技术难度最高的应该就是MIPI协议了,MIPI解码难度之高,令无数英雄竞折腰…...
Map接口及遍历方式
1、Map接口实现类的特点1)Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(无序)2) Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中3) Map 中的key不允许重复import java.util.HashMap; import java…...
一步步构建自己的前端项目
一、我们先把webpack走通 1、先安装相关依赖,webpack是用来处理命令行参数的,但是我不准备使用webpack-cli,但是还是要求必须安装webpack-cli npm install webapck webpack-cli --save-dev2、npm init -y 3、创建项目结构 build.js cons…...
VMware搭建Mac OS环境
推荐阅读 Proxifier逆向分析(Mac) MacOS Burp2021安装配置 突破iOS App双向认证抓包 App绕过iOS手机的越狱检测 iOS系统抓包入门实践之短链 各种学习环境更新MacOS虚拟机 Android和iOS静态代码扫描工具 iOS系统抓包之短链-破解双向证书 Android和iOS应用源码的静态分析…...
【Maven】什么是Maven?Maven有什么用?
目录 一、什么是 Maven 二、Maven 能解决什么问题 三、Maven 的优势举例 四、Maven 的两个经典作用 4.1 Maven 的依赖管理 4. 2 项目的一键构建 💟 创作不易,不妨点赞💚评论❤️收藏💙一下 一、什么是 Maven Maven 的正确发…...
【JavaSE】类和对象的详解
前言: 大家好,我还是那个不会打拳的程序猿。今天我给大家讲解的是类和对象,相信大家在之前的学习中都是面向过程的思想,那么今天就让我们走向面向对象的世界吧。 目录 1.面向过程VS面向对象 1.1什么是面向过程 1.2什么是面向对…...
2023年中职组“网络安全”赛项广西自治区竞赛任务书
2023年中职组“网络安全”赛项 广西自治区竞赛任务书 一、竞赛时间 总计:360分钟 需求环境可私信博主!点个赞加三连吧! 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 A、B模块 A-1 登录安全加固 180分钟 200分 A-2…...
简单的自定义录屏工具
在csdn上写文章,需要配一些操作动态图,需要针对电脑录屏,可能是整个屏幕录屏,也可能是某窗口,甚至是某一小块区域。 动态图最好是gif格式,方便直接嵌入文章中。 一、设计 窗口类widget 切屏类Capturescr…...
数据结构与算法基础(王卓)(17):KMP算法详解(精讲(最简单、直接、有效的思路方法,答案以及代码原理)
本文具体思路参考: (最后证明,该教材/网课实际上是最有效的) DS第四章【3】KMP1_哔哩哔哩_bilibili 中间走的一些弯路的教材: 第06周05--第4章串、数组和广义表5-4.3串的操作--串的匹配算法2--KMP算法_哔哩哔哩_bi…...
【java基础】HashMap源码解析
文章目录基础说明构造器put方法(无扩容,无冲突)put方法(无冲突,有扩容)put方法(有冲突,无树化)put方法(有冲突,树化)remove方法&#…...
实现异步的8种方式,你知道几个?
一、前言 在编程中,有时候我们需要处理一些费时的操作,比如网络请求、文件读写、数据库操作等等,这些操作会阻塞线程,等待结果返回。为了避免阻塞线程、提高程序的并发处理能力,我们常常采用异步编程。 异步编程是一种…...
二叉树的三种遍历
二叉树的遍历可以有:先序遍历、中序遍历、后序遍历先序遍历:根、左子树,右子树中序遍历:左子树、根、右子树后序遍历:左子树、右子树、根下面是我画图理解三种遍历:二叉树里都是分为左子树和右子树。分治思…...
我,30岁程序员被裁了,千万别干全栈
大家好,这里是程序员晚枫,今天是读者投稿。下面开始我们的正文。👇 关注博主👉程序员晚枫 很久了,今天给大家分享一下我从事程序员后,30岁被裁的经历,希望帮到有需要的人。 1、我被裁了 大家好…...
【linux】:进程地址空间
文章目录 前言一、进程地址空间总结前言 本篇文章接着上一篇文章继续讲解进程,主要讲述了进程在运行过程中是如何在内存中被读取的以及为什么要有虚拟地址的存在,CPU在运行过程中是拿到程序的虚拟地址还是真实的物理内存。 一、进程地址空间 下面我们先…...
【保姆级】JMeter Mqtt 压测配置
忽然有个紧急任务要对某个服务做MQTT做压测,紧急实操下JMeter,这里记录下非专业测试员的测试过程、(▽`),欢迎👏大家检查指点( ̄∇ ̄)/下载⏬工具JMeter官方下载地址https://jmeter.apache.org/do…...
C语言数据结构初阶(4)----带头双向循环链表
我们先来看看带头双向循环链表的结构:看到这里我们可能会产生一个想法:这个链表看起来好复杂的样子,是不是它的增删改查比单链表更难写呢?嘿嘿,还真的不是这样的,双向链表的增删改查是很好写的哦࿰…...
原生javascript手写一个丝滑的轮播图
通过本文,你将学到: htmlcssjs 没错,就是html,css,js,现在是框架盛行的时代,所以很少会有人在意原生三件套,通过本文实现一个丝滑的轮播图,带你重温html,css和js基础知识。 为什么选用轮播图做示例&…...
【Linux】进程优先级(进程优先级 Linux下优先级 用top命令更改已存在进程的nice 其他概念 进程切换)
文章目录进程优先级Linux下优先级用top命令更改已存在进程的nice:其他概念进程切换进程优先级 我们作为使用者一般不关心优先级,它跟我们的调度器有很大的关系,调度器是为了跟均衡的调度进程。 什么叫做优先级? 优先级和权限是两…...
2016年chatGPT之父Altman与马斯克的深度对话(值得一看)
2016年9月,现今OpenAI CEO,ChatGPT之父,时任创投公司Y Combinator的总裁Sam Altman在特斯拉加州弗里蒙特工厂采访了埃隆马斯克。马斯克阐述了创建OpenAI的初衷,以及就他而言,对于未来最为重要的五件事。这是OpenAI的两…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
