聊一聊代码重构——封装集合和替换算法的代码实践
代码重构相关内容
聊一聊代码重构——我们为什么要代码重构
聊一聊代码重构——代码中究竟存在哪些坏代码
聊一聊代码重构——关于变量的代码实践
聊一聊代码重构——关于循环逻辑的代码实践
聊一聊代码重构——关于条件表达式的代码实践
聊一聊代码重构——程序方法上的代码实践
聊一聊代码重构——程序方法和类上的代码实践
聊一聊代码重构——存在继承关系类上的代码实践
聊一聊代码重构——封装集合和替换算法的代码实践
封装集合
对集合属性进行封装
很多时候我们封装了对象属性的访问,这能提供属性的安全性,但是对于集合,我们一般会将集合作为一个整体来控制。这使得我们可以直接访问并修改集合,这使得集合变得脆弱。而很多时候我们更加在意的是集合内部的元素的操作,而不是对集合本身进行修改。所以在对象存在集合属性时,需要对集合进行特殊的封装。
需要那些封装
- 在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的两…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?
在建筑行业,项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升,传统的管理模式已经难以满足现代工程的需求。过去,许多企业依赖手工记录、口头沟通和分散的信息管理,导致效率低下、成本失控、风险频发。例如&#…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
