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

.NET 快速重构概要1

1.封装集合

        在某些场景中,向类的使用者隐藏类中的完整集合是一个很好的做法,比如对集合的 add/remove 操作中包 含其他的相关逻辑时。因此,以可迭代但不直接在集合上进行操作的方式来暴露集合,是个不错的主意。

public class Order { private int _orderTotal; private List<OrderLine> _orderLines; public IEnumerable<OrderLine> OrderLines { get { return _orderLines; } } public void AddOrderLine(OrderLine orderLine) { _orderTotal += orderLine.Total; _orderLines.Add(orderLine); } public void RemoveOrderLine(OrderLine orderLine) { orderLine = _orderLines.Find(o => o == orderLine); if (orderLine == null) return; _orderTotal -= orderLine.Total; _orderLines.Remove(orderLine); } } 

        我们对集合进行了封装,没有将 Add/Remove 方法暴露给类的使用者。在.NET Framework 中,有 些类如 ReadOnlyCollection,会由于封装集合而产生不同的行为,但它们各自都有防止误解的说明。这是一 个非常简单但却极具价值的重构,可以确保用户不会误用你暴露的集合,避免代码中的一些 bug。

2.Move方法

        重构同样非常简单,以至于人们并不认为这是一个有价值的重构。迁移方法(Move Method),顾名 思义就是将方法迁移到合适的位置。在开始重构前,我们先看看一下代码:

public class BankAccount
{public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest){AccountAge = accountAge;CreditScore = creditScore;AccountInterest = accountInterest;}public int AccountAge { get; private set; }public int CreditScore { get; private set; }public AccountInterest AccountInterest { get; private set; }public double CalculateInterestRate(){if (CreditScore > 800)return 0.02;if (AccountAge > 10)return 0.03;return 0.05;}
}public class AccountInterest
{public BankAccount Account { get; private set; }public AccountInterest(BankAccount account){Account = account;}public double InterestRate{get { return Account.CalculateInterestRate(); }}public bool IntroductoryRate{get { return Account.CalculateInterestRate() < 0.05; }}
}

         这里值得注意的是 BankAccount.CalculateInterest 方法。当一个方法被其他类使用比在它所在类中的使用还要 频繁时,我们就需要使用迁移方法重构了——将方法迁移到更频繁地使用它的类中。由于依赖关系,该重 构并不能应用于所有实例,但人们还是经常低估它的价值。

最终的代码应该是这样的:

public class BankAccount
{public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest){AccountAge = accountAge;CreditScore = creditScore;AccountInterest = accountInterest;}public int AccountAge { get; private set; }public int CreditScore { get; private set; }public AccountInterest AccountInterest { get; private set; }
}public class AccountInterest
{public BankAccount Account { get; private set; }public AccountInterest(BankAccount account){Account = account;}public double InterestRate{get { return CalculateInterestRate(); }}public bool IntroductoryRate{get { return CalculateInterestRate() < 0.05; }}public double CalculateInterestRate(){if (Account.CreditScore > 800)return 0.02;if (Account.AccountAge > 10)return 0.03;return 0.05;}
}

3.上拉法

上移方法(Pull Up Method)重构是将方法向继承链上层迁移的过程。用于一个方法被多个实现者使用时。

public abstract class Vehicle
{// other methods 
}public class Car : Vehicle
{public void Turn(Direction direction){// code here }
}public class Motorcycle : Vehicle
{
}public enum Direction
{Left,Right
}

        如你所见,目前只有 Car 类中包含 Turn 方法,但我们也希望在 Motorcycle 类中使用。因此,如果没有基类, 我们就创建一个基类并将该方法“上移”到基类中,这样两个类就都可以使用 Turn 方法了。这样做唯一的 缺点是扩充了基类的接口、增加了其复杂性,因此需谨慎使用。只有当一个以上的子类需要使用该方法时 才需要进行迁移。如果滥用继承,系统将会很快崩溃。这时你应该使用组合代替继承。重构之后的代码如 下:

public abstract class Vehicle
{public void Turn(Direction direction){// code here }
}public class Car : Vehicle
{
}public class Motorcycle : Vehicle
{
}public enum Direction
{Left,Right
}

4.下推法

昨天我们介绍了将方法迁移到基类以供多个子类使用的上移方法重构,今天我们来看看相反的操作。重构 前的代码如下:

public abstract class Animal
{public void Bark(){// code to bark }
}public class Dog : A

相关文章:

  • FPGA高端项目:FPGA解码MIPI视频+图像缩放+视频拼接,基于MIPI CSI-2 RX Subsystem架构实现,提供4套工程源码和技术支持
  • element-plus 使el-dropdown只显示当前选择节点
  • 【ARM-Linux篇】u-boot编译
  • 关于IO口的自定义通信协议设计
  • org.apache.kafka.clients.consumer.CommitFailedException
  • MySQL学习——查询示例(三)
  • 【SpringBoot】怎么在一个大的SpringBoot项目中创建多个小的SpringBoot项目,从而形成子父依赖
  • LAMP集群分布式实验报告
  • Java | Leetcode Java题解之第115题不同的子序列
  • 2024.5.31每日一题
  • MapDB:轻量级、高性能的Java嵌入式数据库引擎
  • 算法学习笔记(7.3)-贪心算法(最大切分乘问题)
  • Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南
  • LabVIEW调用外部DLL(动态链接库)
  • 【JVM精通之路】垃圾回收-三色标记算法
  • avalon2.2的VM生成过程
  • create-react-app做的留言板
  • CSS 专业技巧
  • input的行数自动增减
  • session共享问题解决方案
  • Spring Cloud中负载均衡器概览
  • 阿里研究院入选中国企业智库系统影响力榜
  • 彻底搞懂浏览器Event-loop
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 三分钟教你同步 Visual Studio Code 设置
  • 数据结构java版之冒泡排序及优化
  • 一些css基础学习笔记
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • ​软考-高级-系统架构设计师教程(清华第2版)【第9章 软件可靠性基础知识(P320~344)-思维导图】​
  • ​学习一下,什么是预包装食品?​
  • #162 (Div. 2)
  • #中的引用型是什么意识_Java中四种引用有什么区别以及应用场景
  • (2.2w字)前端单元测试之Jest详解篇
  • (bean配置类的注解开发)学习Spring的第十三天
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (原創) 物件導向與老子思想 (OO)
  • (转)c++ std::pair 与 std::make
  • (转)Google的Objective-C编码规范
  • **PHP二维数组遍历时同时赋值
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .NET/C# 中你可以在代码中写多个 Main 函数,然后按需要随时切换
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • @Conditional注解详解
  • @JsonFormat与@DateTimeFormat注解的使用
  • @RunWith注解作用
  • @Service注解让spring找到你的Service bean
  • [ 转载 ] SharePoint 资料
  • []指针
  • [30期] 我的学习方法
  • [AIGC] 广度优先搜索(Breadth-First Search,BFS)详解
  • [Android]RecyclerView添加HeaderView出现宽度问题