美文网首页重构
第八章 重新组织数据

第八章 重新组织数据

作者: rxdxxxx | 来源:发表于2016-03-06 22:29 被阅读81次

重新组织数据

如果你看到一个数组的行为方式很像一个数据结构, 就可以使用 用对象取代数组 把数组变成对象, 从而使这个数据结构更清晰的显露出来. 但这才是第一步, 当你使用移动方法为这个新对象加入相应行为时, 真正的好处才得以体现.

魔法数 --- 也就是带有特殊含义的数字, 你一定会在几天后忘了它的意思, 使用以字面常量取代魔法数 以绝后患.

8.1 Self Encapsulate Field (自封装字段)

你直接访问一个字段, 但与字段之间的耦合关系逐渐变得笨拙

为这个字段建立取值/设值函数, 并且只以这些函数来访问字段.

间接访问变量的好处是, 子类可以通过覆写一个函数而改变获取数据的途径; 它还支持更灵活的数据管理方式, 例如:延迟初始化(懒加载)

如果你想访问超类中的一个字段, 却又想在子类中将对这个变量的访问改为一个计算之后的值, 这就是最该使用本条规则的时候.

8.2 Replace Data Value with Object (以对象取代数据值)

你有一个数据项, 需要与其他数据和行为一起使用才有意义.

将数据项变为对象.

开发初期, 你往往决定以简单的数据项表示简单的情况. 但是随着开发的进行, 你发现简单数据项不在那么简单了. 它们包含了各种不同的含义.

8.3 Change Value to Reference (将值对象改为引用对象)

你从一个类衍生出许多彼此相等的实例, 希望将它们替换为同一个对象

将这个值对象变成引用对象

  • 引用对象:客户,账户这样的东西, 每个对象代表真实世界中的一个实物.
  • 值对象: 日期,这样的东西, 它们完全由其所含的数据值来定义,你并不在意副本的存在.

8.4 Change Reference to Value (将引用对象改为值对象)

你有一个引用对象, 很小且不可变, 而且不易管理

将它变成一个值对象

8.5 Replace Array with Object (以对象取代数组)

你有一个数组, 其中的元素各自代表不同的东西

以对象替换数组. 对于数组中的每个元素, 以一个字段来表示.

数组应该只用于以某种顺序容纳一组相似对象.

8.6 Duplicate Observed Data (复制'被监视数据')

你有一些业务数据置身于GUI控件中, 而业务逻辑方法需要访问这些数据.

  • 领域此处等同于domain 或 业务

将该数据复制到一个业务对象中. 建立一个Observer模式, 用以同步业务对象和GUI对象内的重复数据.

一个分层良好的系统, 应该将处理用户界面和处理业务逻辑的代码分开.

  • 1,你可能需要使用不同的用户界面来表现相同的业务逻辑, 如果同时承担两种责任, 用户界面会变得过分复杂;
  • 2,与GUI隔离之后, 领域对象的维护和演化都会更容易, 你甚至可以让不同的开发者负责不同部分的开发.

8.7 Change Unidirectional Association to Bidirectional (将单向关联改为双向关联)

两个类都需要使用对方特性, 但其间只有一条单向连接.

添加一个反向指针, 并使修改函数能够同时更新两条连接.

8.8 Change Bidirectional Association to Unidirectional (将双向关联改为单向向关联)

两个类之间有双向关联, 但其中一个类如今不再需要另一个类的特性

去除不必要的关联.

双向关联很有用, 但你也必须为它付出代价, 那就是维护双向连接, 确保对象被正确创建和删除而增加的复杂度.

大量的双向关联容易造成僵尸对象: 某个对象本来已经死亡, 却仍然保留在系统中, 因为对它的引用还没有完全清除.

8.9 Replace Magic Number with Symbolic Constant (以字面常量取代魔法数)

你有一个字面数值, 带有特别含义

创造一个常量, 根据其意义为它命名, 并将上述的字面数值替换为这个常量.

8.10 Encapsulate Field (封装字段)

你在类中存在一个public字段

将它声明为private, 并提供相应的访问函数

8.11 Encapsulate Collection (封装集合)

有个函数返回一个集合

让这个函数返回该集合的一个只读副本, 并在这个类中提供添加/移除集合元素的函数.

8.12 Replace Record with Data Class (以数据类取代记录)

你需要面对传统编程环境中的记录结构

为该记录创建一个数据对象.

比如一个遗留接口, 或者从数据库取值. 这些时候你就有必要创建一个接口类, 用以处理这些外来数据.

8.13 Replace Type Code with Class (以类取代类型码)

类之中有一个数值类型码, 但它并不影响类的行为.

以一个新的类替换该数值类型码.

在使用本条之前, 你应该先考虑类型码的其他替换方式.

只有当类型码是纯数据时(也就是类型码不会再switch语句中引起行为变化时), 你才能以类来取代它,

更重要的是: 任何switch语句都应该运用以多态取代条件表达式去掉.

为了进行那样的重构, 你首先必须运用用子类替换类型码以状态/策略模式取代类型码

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

你有一个不可变的类型码, 他会影响类的行为

以子类取代这个类型码

如果你面对的类型码不会影响宿主类的行为, 可以使用以类取代类型码来处理它们.

但如果类型码会影响宿主类的行为, 那么最好的办法就是借用多态来处理变化行为.

一般来说, 这种情况的标志就是像switchif-else结构.

但是以下两种情况你不能那么做:

  • 1,类型码值在对象创建之后发生了改变
  • 2,由于某些原因, 类型码宿主类已经有了子类.

如果你恰好面临这两种情况之一, 就需要使用以状态/策略模式取代类型码

以子类取代类型码的好处在于: 它把对不同行为的了解从类用户那儿转移到了类本身.

8.15 Replace Type Code with State/Strategy (以State/Strategy取代类型码)

你有一个类型码, 它会影响类的行为, 但你无法通过继承手法清除它.

以状态对象取代类型码

如果类型码的值在对象生命期中发生变化其他原因使得宿主类不能被继承你就可以使用本重构.

如果你打算完成本项重构之后再以多态取代条件表达式简化一个算法, 选择Strategy模式比较合适
如果你打算搬移状态相关的数据, 而且你把新建对象视为一种变迁状态, 选择State模式比较合适

8.16 Replace Subclass with Fields (以字段取代子类)

你的各个子类的唯一差别只在返回常数数据的函数身上.

修改这些函数, 使它们返回超类中的某个(新增)字段, 然后销毁子类

不同的子类在函数中硬编码了内容, 把这些返回常数数据的函数, 所返回的数据,作为不同情况下的初始化参数, 再父类的构造函数初始化方法中对这些字段进行赋值, 如果获取对应的信息, 则调用其getter方法, 即消除了子类.

相关文章

  • 第八章 重新组织数据

    重新组织数据 如果你看到一个数组的行为方式很像一个数据结构, 就可以使用 用对象取代数组 把数组变成对象, 从而使...

  • 重新组织数据

    0. 本章内容导图 本章介绍的是如何更好地处理数据的重构手法。 1. 重构手法 1.1 自封装字段 概要:你直接访...

  • 重新组织数据

    重新组织数据 Self Encapsulate Field对于属性的访问采用访问函数的形式。通常这不是必须的,我们...

  • 《重构——改善既有代码的设计》读书笔记3

    参考资料:第七章 在对象之间搬移特性第八章 重新组织数据 第七章:上一章节讲到函数结构的调整,这一章节对对象进行调...

  • 《重构》- 重新组织数据

    一. Self Encapsulate Field(自封装字段) 介绍 场景你直接访问一个字段,但与字段之间的耦合...

  • 重构——重新组织数据

    1 Self Encapsulate Field(自封装字段) 直接访问一个字段,会导致字段之间的的耦合关系过于笨...

  • 容器类型-列表和元祖

    一 概要 二.数据收纳盒 三 列表和元祖的创建 四 列表重新组织

  • 《重构》读书笔记 第八章

    重新组织数据 8.1 Self Encapsulate Field (自封装字段) 为字段建立取值/设值函数,并且...

  • 重构手法--重新组织数据

    1、自封装值域 在对象内部,不直接访问自己的私有属性,而通过get/set方法访问 2、以对象取代数据值 如果某个...

  • 003-重新组织数据

    重新组织数据 1. Self Encapsulate Field(自封装字段) Q:你直接访问一个字段,但与字段之...

网友评论

    本文标题:第八章 重新组织数据

    本文链接:https://www.haomeiwen.com/subject/qvpakttx.html