-
封装记录
动机:记录型结构是多数编程语言提供的一种常见特性。他们能直观地组织起存在关联的数据,让数据作为有意义的单元传递。同时它强迫区分“记录中存储的数据”和“通过计算得到的数据”。对象可以隐藏结构的细节,使对象的用户不需要追究存储的细节和计算过程。另外如果修改字段时,用户可以重命名字段,但同时提供新老字段名的访问方法,这样可以渐进地修改调用方,直到全部替换。做法:
- 对持有记录地变量使用封装变量,将其封装到一个函数中。
- 创建一个类,将记录包装起来,并将记录变量地值替换为该类的一个实例。然后在类上定义一个访问函数,用于返回原始的记录。修改封装变量的函数,令其使用这个访问函数。
- 测试。
- 新建一个函数,让它返回该类的对象,而非那条原始记录。
- 对于该记录的每处使用点,将原先返回记录的函数调用替换为那个返回实例对象的函数调用。使用对象上的访问函数来获取数据的字段,如果该字段的访问函数还不存在,就创建函数。每次更改后进行测试。
- 移除类对原始记录的访问函数,测试。
- 如果记录中的字段本身也是复杂结构,考虑对其再次应用封装记录或封装集合方法。
-
封装集合
动机:封装集合时人们常常犯一个错误:只对集合变量的访问进行了封装,但是依然让取值函数返回集合本身。这使得集合的成员变量可以直接被修改,而封装它的类则全然不知,无法介入。做法:
- 如果集合的引用尚未被封装起来,想用封装变量封装他。
- 在类上添加用于“添加集合元素”和“移除集合元素”的函数。
- 执行静态检查。
- 查找集合的引用点。如果有调用者直接修改集合,令该处调用使用新的添加/移除元素的函数。测试。
- 修改集合的取值函数,使其返回一份只读的数据,可以使用只读代理或数据副本。
- 测试。
-
以对象取代基本类型
动机:开发初期,使用一个简单的数据项就可以表示简单的情况,比如使用字符串或数字等。但随着开发的进行,简单的数据项可能不能够表达其原本的含义。例如:开始用字符串表示“邮箱地址”,但之后又要进行“格式化”、“获取域名”等之类的特殊操作。如果再增加单一的字符串,就会制造出许多重复的代码。做法:
- 如果变量尚未封装,先使用封装变量封装。
- 创建类。用类的构造函数保存这个数据值,并为它提供一个取值函数。
- 执行静态检查。
- 修改第一步得到的设置函数,令其创建一个新类的对象并将其存入字段,如果有必要的话,同时修改字段的类型声明。
- 修改取值函数,令其调用新类的取值函数,并返回结果。
- 测试。
-
以查询取代临时变量
动机:将变量抽取成函数能够使函数分解过程更简单,因为不在需要将变量作为参数传递给函数。将变量的计算逻辑放到函数中,也有助于在函数与函数之间设立清晰的边界。同时也避免了在多个函数中重复编写计算逻辑。做法:
- 检查变量在使用前是否已经完全计算完毕,检查计算代码是否每次都能得到一样的值。
- 如果变量目前不是只读,但是可以改造成只读变量,就先改造。
- 测试。
- 将为变量赋值的代码提炼成函数,确保提炼函数没有副作用。
- 测试,移除临时变量。
-
提炼类
动机:- 类的责任随着业务的添加变得过分负载,不易理解。
- 子类化只影响类的部分特性,或者发现某些特性需要以一种方式来子类化,某些特性则需要另一种方式子类化。
做法:
- 决定如何分解类所负的责任。
- 创建新的类,用以表现从旧类中分离出来的责任。
- 构造旧类时创建一个新类的实例,建立“从旧类访问新类”的链接关系。
- 对于想要迁移的字段,每次更改后运行测试。
- 将必要函数迁移到新类中。先迁移较底层函数(即“被其他函数调用”多于“调用其他函数”的函数),测试。
- 检查两个类的接口,去掉不需要的函数。
- 决定是否公开新类。如果需要,考虑将新类应用改为一个值对象。
-
内联类
动机:- 一个类不在承担足够的责任,不在有单独存在的理由(通常是因为之前的重构移走了这个类的责任)。
- 要重新安排两个类的职责,并让它们产生关联。
做法:
- 对于待内联类(源类)中的所有public函数,在目标类上创建一个对应的函数,新创建的所有函数应该直接委托至源类。
- 修改源类public方法的所有引用点,令它们调用目标类对应的委托方法。测试。
- 将源类中的函数与数据全部搬移到目标类,每次修改之后进行测试,直到源类变为空壳为止。
- 删除源类。
-
隐藏委托关系
动机:每个模块应该尽可能少了解系统的其他部分。如此一来,一旦发生变化,需要了解这一变化的模块就比较少,这会使变化比较容易进行。做法:
- 对于每个委托关系中的函数,在服务对象端建立一个简单的委托函数。
- 调整客户端,令他只调用服务兑现提供的函数,每次调整后测试。
- 如果将来不在有任何客户端需要取用Delegate(受托类),便可移除服务对象中的相关访问函数。
- 测试。
-
移除中间人
动机:随着受托类的功能越来越多,更多的转发函数会使人烦躁。服务类完全变成了一个中间人,此时就应该让客户直接调用受托类。做法:
- 为受托对象创建一个取值函数。
- 对于每个委托函数,让其客户端转为连续的访问函数调用。每次替换后测试。
-
替换算法
动机:有更简单的解决方案时,需要改变原先的算法。更改之前要确定已经尽可能地分解了原先地函数。做法:
- 整理待替代地算法,保证它已经被抽取到一个独立的函数中。
- 先为函数准备测试,以便固定它的行为。
- 准备好另一个算法。
- 执行静态检查。
- 测试。
重构--封装
最新推荐文章于 2024-09-20 09:46:14 发布
本文探讨了编程中的几种关键重构策略,包括封装记录和集合、对象设计、数据项升级、查询优化、类责任分解、内联类、隐藏委托关系以及中间人模式的移除,以提高代码可维护性和性能。
摘要由CSDN通过智能技术生成