为你的项目引入特例!
动机
一种常见的重复代码:一个数据结构的使用者都在检查某个特殊的值,并且当该特殊值出现时所做的处理也都相同。若发现项目中有多处以同样方式应对同一个特殊值,我就会想要把这个处理逻辑收拢到一处。 处理这种情况的一个好办法是使用“特例”(Special Case)模式:创建一个特例元素,用以表达对这种特例的共用行为的处理。这样我就能用一个函数调用取代大部分特例检查逻辑。
特例有几种表现形式:
- 若只需从该对象读取数据,可提供一个字面量对象(literal object),其中所有的值都是预先填充好的
- 若除简单的数值外,还需更多行为,则要创建一个特殊对象,其中包含所有共用行为所对应的函数。特例对象可以由一个封装类来返回,也能通过变换插入一个数据结构。
一个通常需要特例处理的值就是null,这也是这个模式常被叫作“Null对象”(Null Object)模式的原因,我喜欢说:Null对象是特例的一种特例。
做法
从一个作为容器的数据结构(或者类)开始,其中包含一个属性,该属性就是我们要重构的目标。容器的客户端每次使用该属性,都需将其与某个特例值做比对。
希望把该特例值替换为代表这种特例情况的类或数据结构。给重构目标添加检查特例的属性,令其返回false。 创建一个特例对象,其中只有检查特例的属性,返回true。 对“与特例值做比对”的代码运用【提炼函数】,确保所有客户端都使用这个新函数,而不再直接做特例值的比对。
将新的特例对象引入代码中,可以从函数调用中返回,也能在变换函数中生成。 修改特例比对函数的主体,在其中直接使用检查特例的属性。 测试。使用函数组合成类(144)或函数组合成变换(149),把通用的特例处理逻辑都搬移到新建的特例对象中。特例类对于简单的请求通常会返回固定的值,因此可以将其实现为字面记录(literal record)。
对特例比对函数使用内联函数(115),将其内联到仍然需要的地方。
- 点赞
- 收藏
- 关注作者
评论(0)