【《重构 改善既有代码的设计》学习笔记7】在对象之间搬移特性「建议收藏」

本篇文章的内容来自《重构 改善既有代码的设计》一书学习笔记整理并且加上自己的浅显的思考总结!在对象之间搬移特性,核心就是: 决定把责任放在哪儿,重点关注责任,也就是尽量一个类之处理一类事情,或者是某个责任和这个类关系不大,就将此责任移动到关系大的类中。本篇内容两两放在一起,互相对比学习。也更方便理解和记忆。1、搬移函数(Move Method)& 搬移字段(Move field…

大家好,又见面了,我是全栈君。

本篇文章的内容来自《重构 改善既有代码的设计》一书学习笔记整理并且加上自己的浅显的思考总结!

在对象之间搬移特性,核心就是: 决定把责任放在哪儿,重点关注责任,也就是尽量一个类之处理一类事情,或者是某个责任和这个类关系不大,就将此责任移动到关系大的类中。

本篇内容两两放在一起,互相对比学习。也更方便理解和记忆。

1、搬移函数(Move Method)& 搬移字段(Move field)

概要

这两个重构手法,可以类比去学习,本质都是在程序中,有个函数/字段与所在类之外的另一个类有更多的交流。

搬移函数:在目标类中建立一个有着类似行为的新函数,将旧函数变成一个单纯的委托函数,或者将旧函数移除。

搬移函数

搬移字段:在目标类中新建一个字段,修改源字段的所有用户,令它们使用新字段。

搬移字段

动机

”搬移函数“ 的方法在重构中一个很重要的理论支柱,在类中间移动状态(字段)和行为(方法),更是重构中比不可少的措施。随着系统的发展,会发现之前的合理正确的设计策略,到目前来看存在一些问题(不正确)。此时可以进行搬移函数 或者 搬移字段

做法

书中的内容这里不详细展开,只是谈下自己的理解。

♢ 首先找到要移动的函数/字段,移到到目标类中 。(这一步我认为是比较考验业务功能以及对代码的理解力)

♢ 移动完之后,修改所有引用的旧函数/字段的地方,使用新的函数/字段。

♢编译、测试

范例

  • 搬移函数:委托/移除旧函数

搬移函数:委托/移除旧函数 范例

:目标函数需要源类的多个特性,可以使用将源对象传递给目标函数。不过如果目标函数需要太多源类特性,则就得进一步重构。

  • 搬移字段

搬移字段 范例

2、提炼类(Extract Class) & 类内联化(Inline Class)

概要

本质就是:类做了自己不该做的事。

提炼类:**某个类做了应该由两个类做的事。**建立一个新类,将字段和函数从旧类移到新类。(分离)

【《重构 改善既有代码的设计》学习笔记7】在对象之间搬移特性「建议收藏」

类内联化某个类没有做太多事情。 将这个类的所有特性搬移到另一个类中,然后移除原类。(合并)07-2019-03-02_17-02-40-05

动机

一个类应该有清楚的抽象。提炼类和类内联化,两个方式刚好相反。提炼类:类含有大量函数和数据,不好理解,需将它们分离到单独的类中,而类内联化:如果一个类不再承担足够责任,就不再有单独存在的理由。

做法

一个是提炼一个内联化,最主要的是要找到分离的函数和数据和内化的类,其他重构的操作就简单了。具体步骤省略。

范例

  • 提炼类

提炼类 范例

  • 类内联化

和提炼类刚好相反。

内联化 范例

上面两种方式,要在全面理解代码的基础上在进行重构,要求重构的能力还是比较高的。一般项目的代码中的重构不会像上面的例子这么简单。例子只是用来简单说明这种重构方法。

我看到上面的两个重构手法的时候,第一感觉,搞来搞去,有点晕了! 但是细细品读和理解,别有一番滋味。

3、隐藏“委托关系”(Hide Delegate) & 移除中间人(Remove Middle Man)

概要

本质:是否要使用委托关系。两个方法对立。

隐藏“委托关系”:使用委托关系,在服务类上建立客户所需的所有函数,用以隐藏委托关系。

移除中间人:让客户直接调用委托类。

【《重构 改善既有代码的设计》学习笔记7】在对象之间搬移特性「建议收藏」

动机

隐藏“委托关系” : “封装” 即使不是 对象的最关键的特性,也是最关键特性之一。封装 意味着每个对象都应该尽可能少的了解系统的其他部分,如此一来,发生变化。需要了解变化的对象就会更少。

移除中间人:封装 也是要付出代价的,代价就是:每当客户要使用受委托的特性和功能的新特性时候,就必须在服务端添加一个简单的委托函数。很难说什么程度的隐藏才是合适的,在系统的运行过程中不断进行调整。

重构的意义在于:你永远不必说对不起,只要把出问题的地方修补好就行了。

做法

具体略,可参看范例!

范例

  • 隐藏-委托关系

隐藏-委托关系 范例

  • 移除中间人

移除中间人和隐藏 委托关系刚好相反。

移除中间人 范例

4、引入外加函数(Introduce Foregin Method)

概要

你需要为提供服务的类增加一个函数,但你无法修改这个类。在客户类中建立一个函数,并以第一参数形式传入一个服务类。【具体可以看示例】

动机

你在使用一个类,它真的很好,为你提供了需要的所有服务。但是当你需要一项新的服务时候,这个类却无法提供。一般发生在你不能修改这个类的源码。如果可以修改源码,这个外加函数 也就不必使用了。

请记住: 外加函数终归是权宜之计,如果可能,应该将这些函数搬移到它们的理想家园。

做法

具体看范例!

范例

可以理解为,Date有获取 年 、月 、日的服务,但是没有获取当前日期吓一天的日期的能力,而你又不能修改Date的源码,则在客户端加外加一个方法,获取当前日期的下一天的日期。(感觉有点像日期工具类)

外加函数 范例

5、引入本地扩展(Introduce Local Extension)

概要

你需要为服务类提供 一些额外函数,但你无法修改这个类。建立一个新类,使它包含这些额外额函数,让这个扩展品成为源类的子类或者包装类。

动机

项目的发展,有时候你需要一些方法,但是你又不能修改源码,因为要添加的函数多,外加函数很难控制它们。 此时可以使用 子类化 和 包装 两种标准的对象技术,这两种统一称为 本地扩展。

本地扩展 坚持“函数和数据应该统一封装”的原则。在子类和包装类选择的时候,通常选择子类,这样工作量小。

做法

建立子类或者包装类,具体看范例。

范例

  • 子类法

子类法 范例

  • 包装类

包装类需要在包装类中为原始类的所有函数提供 委托函数,比较枯燥乏味。 并且要注意的是,包装类要可以接受包装类或原始类的对象。

包装类 范例

总结

本篇的学习总结是按照对比的方式,最后的这个虽然没有放在一起,但是本质上还是有一点相同,就是在新增功能的你不能修改原服务类的代码,只能进行扩展,如果扩展的少,则使用外加函数,如果建立大量的外加函数,并发现许多类也需要同样的外加函数时候,则考虑使用引用本地扩展的方法。

本章的内容个人觉得还是相对较难,难的不是知识点,而是对代码的设计和理解的能力,什么时候进行重构,怎么样的情况下选择怎么样的重构方法,就本章这几个重构方法,到底如何在真实的项目代码进行操作,如何才能balance,这才是难点。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/121048.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • android游戏开发引擎_android主题引擎

    android游戏开发引擎_android主题引擎随着Android系统的使用越来越广泛,了解一下Android平台下的游戏引擎就非常有必要。而同时因为基于Intelx86的移动设备越来越多,我也非常关注支持x86的移动游戏引擎。然而就目前为止游戏引擎的数量已经非常之多,每个引擎都有不同的特征、价格、成熟度等。通过一些调研之后,我发现有非常多的游戏引擎可用于开发运行在android移动设备端的游戏,其中有些还支持x86系统,另外还有些通过简单的

    2022年10月22日
  • leetcode 两数相加_leetcode数组交集

    leetcode 两数相加_leetcode数组交集原题链接给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。示例 1:输入:l1 = [2,4,3], l2 = [5,6,4]输出:[7,0,8]解释:342 + 465 = 807.示例 2:输入:l1 = [0], l2 = [0]输出:[0]示例 3:输入:l1 = [9,9,9,9,9,9

  • django的orm查询方法_查看django版本命令

    django的orm查询方法_查看django版本命令前言查找是数据库操作中一个非常重要的技术。查询一般就是使用filter、exclude以及get三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都

  • CentOS如何增加虚拟内存?「建议收藏」

    CentOS如何增加虚拟内存?「建议收藏」swap分区的创建1、查看磁盘使用情况2、添加Swap分区使用dd命令创建名为swapfile的swap交换文件(文件名和目录任意):3、对交换文件格式化并转换为swap分区4、挂载并激活分区5、查看新swap分区是否正常添加并激活使用6、修改fstab配置,设置开机自动挂载该分区7、查看是否已经使用了交换内存更改Swap配置查看当前的swappiness数值…

  • MessageDigest详解

    MessageDigest详解一、概述java.security.MessageDigest类用于为应用程序提供信息摘要算法的功能,如MD5或SHA算法。简单点说就是用于生成散列码。信息摘要是安全的单向哈希函数,它接收任意大小的数据,输出固定长度的哈希值。关于信息摘要和散列码请参照《数字证书简介》MessageDigest 通过其getInstance系列静态函数来进行实例化和初始化。MessageDigest对象通…

  • Vista/Win7 使用Vista Loader激活后的 Windows/Linux双启动解决方案

    Vista/Win7 使用Vista Loader激活后的 Windows/Linux双启动解决方案Windows与Linux的双启动,一般使用Grub4Dos(以下简称Grub)来作双启动的工具。自从使用VistaLoader来“软改”bios来激活Vista/Win7后

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号