重构复杂简单变量之用子类替换类型码

子类替换类型码 是一种用于将类型码替换为子类。当代码使用类型码(通常是 intstringenum)来表示对象的不同类别,并且这些类别的行为有所不同时,使用子类可以更加清晰地表达这些差异并减少复杂的条件判断。

一、什么时候使用

  • 当我们发现不同的类型码对应的对象行为有所不同,并且在代码中使用 if-elseswitch-case 语句来处理不同类型的行为。
  • 当类型码背后的行为变得越来越复杂,处理逻辑变得难以维护。
  • 当每个类型码代表的类别可能拥有不同的属性或方法时。

二、优化步骤

  1. 识别类型码:找到那些使用类型码来区分对象行为的地方,通常是用来驱动 if-elseswitch-case 语句。
  2. 为每个类型创建子类:为每个类型码创建一个对应的子类,从原类继承。
  3. 将行为移植到子类:把与类型码相关的不同行为从原来的条件语句中提取出来,移动到各个子类中。
  4. 替换类型码:在对象实例化的地方,使用子类来代替类型码。

三、示例

假设我们有一个 Employee 类,使用类型码 EmployeeType 来表示全职员工和兼职员工,并根据类型码的不同计算奖金:

public class Employee
{public int EmployeeType { get; set; } // 1: Full-time, 2: Part-timepublic decimal GetBonus(){if (EmployeeType == 1){return 1000;}else if (EmployeeType == 2){return 500;}else{throw new ArgumentException("Invalid employee type.");}}
}
3.1 优化后的代码

可以为全职和兼职员工创建子类,消除类型码并让每个子类自行实现 GetBonus 方法:

public abstract class Employee
{public abstract decimal GetBonus();
}public class FullTimeEmployee : Employee
{public override decimal GetBonus(){return 1000;}
}public class PartTimeEmployee : Employee
{public override decimal GetBonus(){return 500;}
}

在客户端代码中,实例化不同的员工子类:

Employee fullTimeEmployee = new FullTimeEmployee();
Employee partTimeEmployee = new PartTimeEmployee();Console.WriteLine(fullTimeEmployee.GetBonus()); // 输出 1000
Console.WriteLine(partTimeEmployee.GetBonus()); // 输出 500

四、优化的好处

  1. 消除条件判断:不同类型的行为由各自的子类负责,不再需要通过 if-elseswitch-case 来判断类型,简化了代码结构。
  2. 增强可扩展性:新增类型时,只需创建新的子类,不需要修改现有的代码,从而遵循了开闭原则(Open/Closed Principle)。
  3. 集中职责:每个子类专门处理与它相关的行为,职责更加单一,符合单一职责原则(Single Responsibility Principle)。
  4. 更具可读性和维护性:每个子类的行为清晰且独立,代码更易于理解和维护。

五、适用场景

  • 多态场景:当不同类型的对象有不同的行为表现时,使用子类可以充分利用面向对象编程的多态性。
  • 复杂条件逻辑:当处理类型码的条件判断过于复杂或冗长时,将类型码替换为子类能够减少这些复杂的条件逻辑。
  • 未来类型扩展:如果预期会增加新的类型码,使用子类可以避免频繁修改现有代码。

六、示例扩展

如果不同员工类型除了奖金计算之外还涉及其他不同的业务逻辑,比如工资计算、休假天数等,用子类封装这些行为将使代码更加清晰。每个子类不仅仅是实现不同的 GetBonus,还可以根据需要扩展其他专属行为。

public abstract class Employee
{public abstract decimal GetBonus();public abstract int GetVacationDays();
}public class FullTimeEmployee : Employee
{public override decimal GetBonus(){return 1000;}public override int GetVacationDays(){return 20;}
}public class PartTimeEmployee : Employee
{public override decimal GetBonus(){return 500;}public override int GetVacationDays(){return 10;}
}

使用子类替代类型码能够让代码结构更加简洁、易维护,并且提升了扩展性。不同类型的对象通过子类来管理各自的行为,充分利用了面向对象编程的多态特性,从而减少复杂的条件判断和潜在错误。

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

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

相关文章

SQL 自学:游标(Cursors)的理解与应用

在 SQL 中,游标(Cursor)是一种用于处理从数据库中检索出的多行数据的机制。它允许我们逐行地处理查询结果集,而不是一次性处理整个结果集。 一、游标是什么 游标可以看作是一个指向结果集的指针。通过游标,我们可以在…

深度学习:终身学习(Life-Long Learning)详解

终身学习(Life-Long Learning)详解 终身学习(也称为持续学习或增量学习)是机器学习中的一个重要研究领域,它关注如何使机器学习模型在完成一系列任务后,能够持续学习新任务,而不会忘记之前学到…

集合框架07:LinkedList使用

1.视频链接:13.14 LinkedList使用_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?spm_id_from333.788.videopod.episodes&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5&p142.LinkedList集合的增删改查操作 package com.yundait.Demo01;im…

【判断推理】逻辑论证之归因论证

2.1 归因论证概述 归因:指人们对 他人或自己行为的原因的推论过程。具体而言,就是观察者对他人的行为过程或自己的行为过程所进行的因果解释和推论。(通俗而言,归因就是对已经发生的事实,在众多可能的原因中找出一个原…

【大模型问答测试】大模型问答测试脚本实现(第二版)——接入pytest与代码解耦

背景 接上一篇,【大模型问答测试】大模型问答测试脚本实现(第一版)。 在实现自动化的时候,原先把很多方法与request请求写在一块了,趁着目前实现接口数量较少,决定对代码进行解耦,并且清晰目录…

Qt获取磁盘信息+表格显示

效果展示 主要代码 获取磁盘相关数据 获取磁盘数据 Qt 没有提供相关的接口,需要使用 Windows API。接口解释如下: BOOL GetDiskFreeSpaceExW([in, optional] LPCWSTR lpDirectoryName,[out, optional] PULARGE_INTEGER lpFreeBytesAvailable…

MongoDB Shell 基本命令(一)

MongoDB Shell 基本命令(一) 1. 基本概念 SQL术语/概念MongoDB术语/概念解释/说明databasedb数据库tablecollection数据库表/集合rowdocument数据记录行/文档columnfield数据字段/域indexindex索引table joins表连接,MongoDB不支持primary keyprimary key主键,Mon…

推荐算法的学习

文章目录 前言1、模型1.1 从本领域模型的发展历史中学习1.1.1 在历史中总结发展规律和趋势1.1.2 发现模型之间的共性,方便记忆 1.2 从其他领域的发展中学习1.2.1 注意力机制1.2.2 残差网络 1.3 实践该怎么办? 2、 特征2.1 数据源的选择与建立2.2 特征构造…

Python生成随机密码脚本

引言 在数字化时代,密码已成为我们保护个人信息和数据安全的重要手段。然而,手动创建复杂且难以猜测的密码是一项既繁琐又容易出错的任务。幸运的是,Python编程语言为我们提供了一种高效且灵活的方法来自动生成随机密码。本文将详细介绍如何…

android app执行shell命令视频课程补充android 10/11适配-千里马android

(https://blog.csdn.net/learnframework/article/details/120103471) https://blog.csdn.net/learnframework/article/details/120103471 hi,有学员在学习跨进程通信专题课程时候,在实战app执行一个shell命令的项目时候,对课程本身的android …

Day3 线性表(Linear List)

Day3 线性表(Linear List) 定义: 是具有相同数据类型的n(n>0)个数据元素的有限序列,其中n为表长,当n0时线性表是一个控标。若用L命名线性表,则其一般表示为:L(a1,a2,a3,a4,.....ai,ai1....…

【高等数学】无穷级数

0. 了解 无穷级数是指将无穷多个数按照一定的规律相加起来的表达式。 打个比方,就像你有一个无穷长的梯子,每一级梯子代表一个数。把这些数一个一个加起来,就形成了无穷级数。 比如常见的等比级数,这里是首项,是公比。如果,这个等比级数是收敛的,也就是它的和是一个有限…

Hackmyvm-Lookup

0x00信息收集 0x01端口扫描 PORT STATE SERVICE 22/tcp open ssh 80/tcp open http MAC Address: 08:00:27:0A:44:CF (Oracle VirtualBox virtual NIC)22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)80/tcp open http Apache ht…

数据权限的设计与实现系列13——前端筛选器组件Everright-filter集成多控制维度实现

‍ 数据权限多维度实现 上面的所有工作,实际都是基于业务实体属性这一数据权限控制维度展开的。 接下来,我们来设计与实现多维度,主要是用户组(即角色)、组织机构和用户。 ‍ 业务需求分析 用户控制维度 业务场景…

【latex中三线表格】

在 LaTeX 中,三线表格(也称为 “三线表” 或 “三线式表格”)通常使用 booktabs 宏包来实现。这种表格通过三条水平线(表头上、表头下、表格底部)来简洁地展示表格数据。下面是一个创建三线表格的 LaTeX 代码示例&…

【MATLAB代码】指纹定位方法(KNN)介绍与例程(二维、轨迹定位),源代码可复制粘贴到MATLAB上运行

文章目录 指纹定位指纹定位技术简介基本原理位置估算公式1. 最近邻居算法(KNN)2. 加权最近邻居算法(W-KNN)3. 最小二乘法(LS)最终位置 P P P通过求解下面的方程获得:应用场景优缺点优点缺点总结源代码代码运行运行方法运行结果指纹定位 指纹定位技术简介 指纹定位是一…

一文讲清楚 OAuth 2.0 支持的四个授权流程

目录 1、授权码授权流程(Authorization Code Grant) 2、隐式授权流程(Implicit Grant) 3、密码凭证授权流程(Resource Owner Password Credentials Grant) 4、客户端凭证授权流程(Client Cre…

python 更换pip源

你可以通过修改 pip 的配置文件来换源。以下是步骤: 创建或编辑 ~/.pip/pip.conf(Linux/macOS)或 %USERPROFILE%\pip\pip.ini(Windows)。 添加以下内容以更换为阿里云源为例: [global] index-url https…

SpringBoot日常:封装redission starter组件

文章目录 逻辑实现POM.xmlRedissionConfigRedissionPropertiesRedissionUtilsspring.factories 功能测试application.yml配置POM.xmlTestController运行测试 本章内容主要介绍如何通过封装相关的redission连接配置和工具类,最终完成一个通用的redission starter。并…

洛谷 P1038 [NOIP2003 提高组] 神经网络(拓扑排序)

题目传送门 感觉这道题需要我们高超的语文阅读水平…… 解题思路 我们发现要计算一个细胞的状态值(),就需要先算出有边指向它的其他细胞对答案的贡献; 这是有拓扑序的,所以我们想到拓扑排序。 题目中说了&#xff0…