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

聊一聊代码重构——封装集合和替换算法的代码实践

代码重构相关内容

聊一聊代码重构——我们为什么要代码重构

聊一聊代码重构——代码中究竟存在哪些坏代码

聊一聊代码重构——关于变量的代码实践

聊一聊代码重构——关于循环逻辑的代码实践

聊一聊代码重构——关于条件表达式的代码实践

聊一聊代码重构——程序方法上的代码实践

聊一聊代码重构——程序方法和类上的代码实践

聊一聊代码重构——存在继承关系类上的代码实践

聊一聊代码重构——封装集合和替换算法的代码实践


封装集合

对集合属性进行封装

很多时候我们封装了对象属性的访问,这能提供属性的安全性,但是对于集合,我们一般会将集合作为一个整体来控制。这使得我们可以直接访问并修改集合,这使得集合变得脆弱。而很多时候我们更加在意的是集合内部的元素的操作,而不是对集合本身进行修改。所以在对象存在集合属性时,需要对集合进行特殊的封装。

需要那些封装

  1. 在getter方法中,返回集合的一个只读拷贝,以防止外部代码修改集合。
  2. 在setter方法中,进控制,将对集合的修改限制在元素上的修改。
  3. 对集合添加对集合元素内操作的方法。

就像下面对属性的封装

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 方法进行访问。

替换算法

很多时候在最开始实现业务的时候对业务最终展现的形式不是很清晰,或者因为时间原因我们只能选择最快实现业务的方式。但是这些内容有可能并不是最好的方式,在原先的做法之外,可能存在更简单的解决方案,此时在重构代码时需要尝试对原来算法进行重构。比如使用更高效的算法替代低效算法,使用已经存在的三方库中方法替代自己编写的方法等。

如何进行算法替换

  1. 选择一个可以替换当前算法的新算法。
  2. 如果新的算法不是三方库中已有的内容,则将新算法实现为一个新的方法。
  3. 在原方法调用地方切换为新方法。
  4. 测试正确性,比较新算法的性能。

什么样的内容要替换算法

  1. 使用高效算法替换低效的算法

  2. 使用高可读性的算法替换低可读性算法

引入特例

特殊的逻辑

正常业务中,即使逻辑分支不同,但是其需要经历的流程大多是类似的,这个时候我们使用一些系列公共逻辑将其抽象。后来的开发同学在理解这些内容时会更加容易。但是某些时候,总会有某个特殊的逻辑分支在业务逻辑或者涉及数据范围都和其他分支差异巨大。为了不破坏原有代码结构和设计,又不想在父类中添加太多的特定逻辑。我们可以声明一个特殊标记的专门类来处理这个逻辑,需要处理这个逻辑的地方调用这个特例类的方法。这个特例类通常是一个继承自父类的子类,但是只包含特定的逻辑处理,不包含其他的业务逻辑。这样既完成了特殊处理,又保持原有的代码结构和设计,避免对原有代码的影响和破坏。但是,过度使用引入特例可能会导致代码过于复杂和难以维护,因此需要根据具体情况进行选择和使用。

下面情况下可以考虑使用引入特例的重构

  1. 如果业务分支中,存在大量针对特殊情况的判断和处理,并且这些特殊情况的处理逻辑相同。

  2. 特殊分支处理逻辑和正常情况的处理逻辑内容迥异,其逻辑会影响对正常逻辑的理解和扩展。

尝试引入特例的

  1. 审查代码,找出代码中符合上面描述的特殊情况。
  2. 创建一个特例类,该类应该继承自原来的类,并重写特殊情况下的方法。
  3. 在原来的类中添加一个方法,用于判断当前是否为特殊情况。
  4. 在原来的类中,将特殊情况下的代码替换为使用特例类的代码。如果当前为特殊情况,则创建特例类的实例并调用其方法,否则调用原来的方法。
  5. 测试

下面是一个使用特例方式重构的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));}}......
}
http://www.lryc.cn/news/39169.html

相关文章:

  • FPGA解码4K分辨率4line MIPI视频 OV13850采集 提供工程源码和技术支持
  • Map接口及遍历方式
  • 一步步构建自己的前端项目
  • VMware搭建Mac OS环境
  • 【Maven】什么是Maven?Maven有什么用?
  • 【JavaSE】类和对象的详解
  • 2023年中职组“网络安全”赛项广西自治区竞赛任务书
  • 简单的自定义录屏工具
  • 数据结构与算法基础(王卓)(17):KMP算法详解(精讲(最简单、直接、有效的思路方法,答案以及代码原理)
  • 【java基础】HashMap源码解析
  • 实现异步的8种方式,你知道几个?
  • 二叉树的三种遍历
  • 我,30岁程序员被裁了,千万别干全栈
  • 【linux】:进程地址空间
  • 【保姆级】JMeter Mqtt 压测配置
  • C语言数据结构初阶(4)----带头双向循环链表
  • 原生javascript手写一个丝滑的轮播图
  • 【Linux】进程优先级(进程优先级 Linux下优先级 用top命令更改已存在进程的nice 其他概念 进程切换)
  • 2016年chatGPT之父Altman与马斯克的深度对话(值得一看)
  • 基于vscode开发vue3项目的详细步骤教程 3 前端路由vue-router
  • 【C语言】每日刷题 —— 牛客语法篇(5)
  • 操作系统(2.1)--进程的描述与控制
  • JAVA查看动态代理类
  • Chapter2 : SpringBoot配置
  • 手撕单链表练习
  • Kubuntu安装教程
  • [蓝桥杯] 树状数组与线段树问题(C/C++)
  • Matlab-Loma Prieta 地震分析
  • Spring Boot全局异常处理
  • websocket每隔5秒给服务端send一次信息