重构改善既有代码的设计-学习(六):处理继承关系

news2024/12/23 20:59:06

1、函数上移(Pull Up Method)

 

        无论何时,只要系统内出现重复,你就会面临“修改其中一个却未能修改另一个”的风险。通常,找出重复也有一定的难度。

        所以,某个函数在各个子类中的函数体都相同(它们很可能是通过复制粘贴得到的),这就需要使用函数上移,也就是将共同的函数上移到超类中

        函数上移过程中,被提升的函数可能会引用只出现于子类而不出现于超类的特性。此时,我就得用字段上移函数上移先将这些特性(类或者函数)提升到超类。 

2、字段上移(Pull Up Field) 

 

         如果各子类是分别开发的,或者是在重构过程中组合起来的,你常会发现它们拥有重复特性,特别是字段更容易重复。

        如果它们被使用的方式很相似,就可以将它们提升到超类中去。 

3、构造函数本体上移(Pull Up Constructor Body) 

 

        逐一移除子类间的公共代码,将其提升至超类构造函数中。对于公共代码中引用到的变量,将其作为参数传递给超类的构造函数。

        如果重构过程过于复杂,可以考虑转而使用以工厂函数取代构造函数(详见:重构改善既有代码的设计-学习(五):重构API-CSDN博客)。

4、函数下移(Push Down Method)

 

        如果超类中的某个函数只与一个(或少数几个)子类有关,那么最好将其从超类中挪走,放到真正关心它的子类中去。 

5、字段下移(Push Down Field) 

 

        如果某个字段只被一个子类(或者一小部分子类)用到,就将其搬移到需要该字段的子类中。 

6、以子类取代类型码(Replace Type Code with Subclasses) 

 

        软件系统经常使用类型码表现“相似但又不同的东西”。大多数时候,有这样的类型码就够了。但也有些时候,可以再多往前一步,引入子类。

        继承有两个诱人之处:

  1. 你可以用多态来处理条件逻辑。如果有几个函数都在根据类型码的取值采取不同的行为,多态就显得特别有用。引入子类之后,我可以用以多态取代条件表达式(详见:重构改善既有代码的设计-学习(四):简化条件逻辑-CSDN博客)来处理这些函数。 
  2. 有些字段或函数只对特定的类型码取值才有意义,此时可以创建子类,然后用字段下移把这样的字段放到合适的子类中去。

        例如:

function createEmployee(name, type) {
    return new Employee(name, type);
}

        改为:

function createEmployee(name, type) {
    switch (type) {
        case "engineer": return new Engineer(name);
        case "salesman": return new Salesman(name);
        case "manager": return new Manager (name);
    }
}

7、移除子类(Remove Subclass) 

 

        子类数据结构的多样和行为的多态提供支持,它们是针对差异编程的好工具。但随着软件的演化,子类所支持的变化可能会被搬移到别处,甚至完全去除,这时子类就失去了价值。有时添加子类是为了应对未来的功能,结果构想中的功能压根没被构造出来,或者用了另一种方式构造,使该子类不再被需要了。 

8、提炼超类(Extract Superclass)

 

         如果看见两个类在做相似的事,可以利用基本的继承机制把它们的相似之处提炼到超类

9、折叠继承体系(Collapse Hierarchy) 

 

         如果发现一个类与其超类已经没多大差别,不值得再作为独立的类存在,就需要把超类和子类合并起来

10、 以委托取代子类(Replace Subclass with Delegate)

 

        如果一个对象的行为有明显的类别之分,继承是很自然的表达方式。我可以把共用的数据和行为放在超类中,每个子类根据需要覆写部分特性。

        但继承也有其短板,他只能用于处理一个方向上的变化,并且继承给类之间引入了非常紧密的关系。在超类上做任何修改,都很可能破坏子类。

        用委托可以解决这两个问题。对于不同的变化原因,我可以委托给不同的类。与继承关系相比,使用委托关系时接口更清晰、耦合更少。

        可以用设计模式来理解本重构手法,就是用状态(State)模式或者策略(Strategy)模式
取代子类。这两个模式在结构上是相同的,都是由宿主对象把责任委托给另一个继承体系。

        例子:

class Order {
    get daysToShip() {
        return this._warehouse.daysToShip;
    }
}

class PriorityOrder extends Order {
    get daysToShip() {
        return this._priorityPlan.daysToShip;
    }
}

        改为:

class Order {
    get daysToShip() {
        return (this._priorityDelegate)
            ? this._priorityDelegate.daysToShip
            : this._warehouse.daysToShip;
    }
}

class PriorityOrderDelegate {
    get daysToShip() {
        return this._priorityPlan.daysToShip
    }
}

11、以委托取代超类(Replace Superclass with Delegate) 

 

        在对象技术发展早期,有一个经典的误用继承的例子:让栈(stack)继承列表(list)。这个想法的出发点是想复用列表类的数据存储和操作能力。虽说复用是一件好事,但这个继承关系有问题:列表类的所有操作都会出现在栈类的接口上,然而其中大部分操作对一个栈来说并不适用。更好的做法应该是把列表作为栈的字段,把必要的操作委派给列表就行了。 

         如果子类与超类之间的耦合过强,超类的变化很容易破坏子类的功能,此时就可以使用以委托取代超类。

        这样做的缺点就是,对于宿主类(也就是原来的子类)和委托类(也就是原来的超类)中原本一样的函数,现在我必须在宿主类中挨个编写转发函数。

        例子:

class List {...}
class Stack extends List {...}

        改为:

class Stack {
    constructor() {
        this._storage = new List();
    }
}
class List {...}

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

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

相关文章

leetcode hot100跳跃游戏Ⅱ

本题和上一题还是有不一样的地方,这个题中,我们需要记录我们跳跃的步数并尽可能的满足最小的跳跃步数到达终点。 那么我们还是采用覆盖范围的概念,但是我们需要两个,一个是在当前位置的覆盖范围,另一个是下一步的覆盖…

Linux的 .bashrc 有什么作用?

一、.bashrc 是什么? 有什么用? .bashrc是一个存储在你的home目录下的隐藏文件,它用来配置和自定义你的终端环境和行为。 每次你启动一个新的终端时,.bashrc文件就会被执行,加载你设置的环境变量,别名,函数…

深度学习-自注意力机制

文字编码 one-hot编码,让模型自己去学习怎么进行编码 常见的输出 1.每个词都有一个输出值 2.每个句子输出一个值,情感分类 3.输入与输出长度不对应,翻译任务,生成任务。 RNN最早的语言处理 RNN解决的是模型去考虑前面的输入…

数字图像处理(实践篇)二十八 使用OpenCV Python中的K-means对图像进行颜色量化处理

目录 1 颜色量化 2 实践 在某些时候,不可避免的某些设备只能生成有限数量的颜色。因此需要执行颜色量化。选择使用cv2.kmeans()函数对颜色量化应用k-means聚类。 1 颜色量化 使用K-means聚类在图像中实现颜色量化的步骤如下: ① 导入依赖库

js实现动漫拼图2.0版

比较与1.0版,2.0版就更像与华容道类似的拼图游戏,从头到尾都只能控制白色块移动,而且打乱拼图和求助的实现与1.0都不相同 文章目录 1 实现效果2 实现思路2.1 打乱拼图2.2 求助功能2.3 判赢 3 代码实现 js实现动漫拼图1.0版 https://blog.csdn…

【千亿生意】一张眼底图,浮现你未来十年身体1000多种疾病风险

【千亿生意】一张眼底图,浮现你未来十年身体1000多种疾病风险 一眼看全身鹰瞳思路眼底看全身论文眼底成像技术眼底看肝脏眼底看多囊卵巢综合征眼底看肺部眼底看贫血眼底看少肌症眼底看神经退行眼底看心血管眼底看肾脏 鹰瞳视网膜论文 一眼看全身 眼病,是…

Redisson分布式锁介绍及实战应用(防止缓存击穿)

本地锁 浏览器把100w请求由网关随机往下传,在集群情况下,每台服务都放行10w请求过来,这时候每台服务都用的是本地锁是跨JVM的, 列如这些服务都没有49企业,此时有几个服务进行回原了打击在DB上面,那后期把这…

fastapi报错

初始化报错,非常低级错,扇自己10八张 app FastApi()

如何在Shopee越南站点进行有效的选品

在如今的电商市场中,选品是卖家们取得成功的关键之一。在Shopee越南站点进行选品时,卖家可以采取一些策略来提高产品的竞争力和销售业绩。本文将介绍一些有效的选品策略,帮助卖家在Shopee越南站点取得成功。 先给大家推荐一款shopee知虾数据…

算法沉淀——二分查找(leetcode真题剖析)

算法沉淀——二分查找 01.二分查找02.在排序数组中查找元素的第一个和最后一个位置03.搜索插入位置04.x 的平方根05.山脉数组的峰顶索引06.寻找峰值07.寻找旋转排序数组中的最小值08.LCR 173. 点名 二分查找(Binary Search)是一种在有序数组中查找特定元…

【服务器APP】利用HBuilder X把网页打包成APP

目录 🌺1. 概述 🌼1.1 新建项目 🌼1.2 基础配置 🌼1.3 图标配置 🌼1.4 启动界面配置 🌼1.5 模块配置 🌼1.6 打包成APP 🌺1. 概述 探讨如何将网页转化为APP,这似乎…

【大厂AI课学习笔记】1.3 人工智能产业发展(1)

我国人工智能政策,分为5个阶段。从探索期,到后面的4个阶段。 MORE:(以下为文心一言4.0的参考内容,和腾讯课程资料的分阶段,略有不同) 我国的人工智能政策发展可以大致分为以下几个阶段,每个阶段…

网络防御安全知识(第三版)

配置黑洞路由 --- 黑洞路由即空接口路由,在NAT地址池中的地址,建议配置达到这个地址指 向空接口的路由,不然,在特定环境下会出现环路。(主要针对地址池中的地址和出接口地址 不再同一个网段中的场景。) …

一文解锁——那些你不太了解的AI!

ChatGPT现象级走红,国内也有文心一言等模型紧随其后,彻底将大语言模型送上大热门。 不管是你是否深度应用过这些模型,不可否认的是,AI已经彻底地融入我们的生活,甚至成为赚钱利器。除了ChatGPT和百度的文心一言&#…

力扣712. 两个字符串的最小ASCII删除和

动态规划 思路: 假设 dp[i][j] 是 s1 长度 i 和 s2 长度 j 两个字符串的最小 ASCII 删除和;dp[i][j] 可以由: 如果 s1 的第 i 个字符(s1[i - 1])和 s2 的第 j 个字符(s2[j - 1])不相等&#xf…

详解SpringCloud微服务技术栈:ElasticSearch实战(旅游类项目)

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:详解SpringCloud微服务技术栈:ElasticSearch实践2——RestClient查询并处理文档 📚订阅专栏:…

【JavaScript 基础入门】01 编程语言和计算机基础

编程语言和计算机基础 目录 编程语言和计算机基础1 - 编程语言1.1 编程1.2 计算机语言1.3 编程语言1.4 翻译器1.5 编程语言和标记语言区别1.6 总结 2 - 计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 1 - 编程语言 1.1 编程 编程: 就是让计算…

运放反馈电阻上并联小电容的作用

这是一个同相比例运算放大电路, Rf是反馈电阻 有的电路还会在反馈电阻上并联一个小电容,一般在几pF到几十pF。 那么这个电容有什么作用呢?其实这个电容是一个相位补偿电容,防止运放自激振荡的。另外这个电容也有抑制高频噪声的作用…

GoogleNet Inception v2 和 Inception v3详解

1 GoogleNet Inception v2 v1具体结构: v2具体结构: 1 引入Batch Normalization(BN): Inception v2在每个卷积层之后引入了BN。这有助于解决深层网络中的梯度消失问题,同时加快训练过程并提高模型的收敛速度。BN通过…

鸿蒙首批原生应用!无感验证已完美适配鸿蒙系统

顶象无感验证已成功适配鸿蒙系统,成为首批鸿蒙原生应用,助力鸿蒙生态的快速发展。 作为全场景分布式操作系统,鸿蒙系统旨在打破不同设备之间的界限,实现极速发现、极速连接、硬件互助、资源共享。迄今生态设备数已突破8亿台&…