第八章 重新组织数据

重新组织数据

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

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

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方法, 即消除了子类.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容

  • 1 Self Encapsulate Field(自封装字段) 直接访问一个字段,会导致字段之间的的耦合关系过于笨...
    hklbird阅读 534评论 0 0
  • 《重构》读书笔记 总览 第一部分 第一章从实例程序出发,展示设计的缺陷,对其重构可以了解重构的过程和方法。 第二部...
    白桦叶阅读 2,387评论 2 5
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,175评论 9 118
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,602评论 18 399
  • 强势的人未必是强者 强势的人未必是强者。一个真正聪明的人,是懂得如何让自己委屈求全的人。刚者易折,柔则长存。“任性...
    xcy无名阅读 416评论 0 0