重构之重新组织数据

一.自封装字段
你直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙。为这个字段建立取值/设值函数,并且只以这些函数来访问字段。
在字段访问方式这个问题上,存在两种截然不同的观点。其中一派认为,在该变量定义所在的类中,你可以自由访问它;另一派认为,即使在这个类中你也应该只使用访问函数间接访问。两派之间的争论客户已说是如火如荼。归根结底,间接访问变量的好处是,子类可以通过覆写一个函数而改变获取数据的途径,它还支持更灵活的数据管理方式,例如延迟初始化(意思是:只有在需要用到某值时,才对它初始化)。直接访问变量的好处则是:代码比较容易阅读。面临选择时,就我自己而言,我比较喜欢先使用直接访问方式,知道这种方式带来麻烦为止。
二.以对象取代数据值
你有一个数据项,需要与其他数据和行为一起使用才用意义。开发初期,你往往决定以简单的数据项表示简单的情况。但是,随着开发的进行,你可能会发现,这些简单数据项不再那么简单了。比如说,一开始你可能会用一个字符串来表示电话号码的概念,但是随后你会发现,电话号码需要格式化,抽取区号之类的特殊行为。如果这样的数据项只有一两个,你还可以把相关函数放进数据项所属的对象里。但是重复代码坏味道和依恋清洁坏味道很快就会从代码中散发出来。当这些坏味道开始出现,你就应该将数据值变成对象。
三.将值对象改为引用对象
你从一个类衍生出许多彼此相等的实例,希望将它们替换为同一个对象。在许多系统中,你都可以对对象做一个有用的分类,引用对象和值对象。前者就像客户,账户这样的东西,每个对象代表真实世界中的一个实物,你可以直接以相等操作符(==)检查两个对象是否相等。后者则是像日期,钱这样的东西,它们完全由其所含的数据值来定义,你并不在意副本的存在,系统中或许存在成百上千个内容为"1/1/2000"的日期对象,当然你需要知道两个值对象是否相等,需要覆写equals()方法。要在引用对象和值对象之间做选择有时并不容易。有时候你会从一个简单的值对象开始,在其中保存少量不可修改的数据。而后,你可能会希望给这个对象加入一些可修改数据,并确保对任何一个对象的修改都能影响到所有引用此对象的地方。这时候你就需要将这个对象编程一个引用对象。
四.以对象取代数组
你有一个数组,其中的元素各自代表不同的东西。数组是一种常见的用以组织数据的结构,不过他们应该只用于"以某种顺序容纳一组相似对象"。有时候你会发现,一个数组容纳了多种不同对象,这会给用户带来麻烦,因为他们很难记住像数组的第一个元素时人名这样的约定。对象就不同了,你可以运用字段名称和函数名称来传达这样的信息,因此你无须死记它,也无需依赖注释。
五.复制被监视数据
你有一些领域数据置身于GUI控件中,而领域函数需要访问这些数据,将该数据复制到一个领域对象中,建立一个Observer模式,用以同步领域对象和GUI对象内的重复数据。
一个分层良好的系统,应该将处理用户界面和处理业务逻辑的代码分开。之所以这样做,原因有以下几点:
1.你可能需要使用不同的用户界面来表现相同的业务逻辑,如果同时承担两种责任,用户界面会变得过分复杂。
2.与GUI隔离之后,领域对象的维护和演化都会更容易,你甚至可以让不同的开发者负责不同部分的开发。
尽管可以轻松地将行为划分到不同部位,数据却往往不能如此。同一项数据有可能既需要内嵌于GUI控件,也需要保存于领域模型里。自从MVC模式出现后,用户界面框架都使用多层系统来提供某种机制,使你不但可以提供这类数据,并保持它们同步。如果你遇到的代码是以两层方式开发,业务逻辑被内嵌于用户界面之中,你就有必要将行为分离出来。其中的主要工作就是函数的分解和搬移。但数据就不同了,你不能仅仅只是移动数据,必须将它复制到新的对象中,并提供相应的同步机制。
六.以字段取代子类
你的各个子类的唯一差别只在返回常量数据的函数身上。修改这些函数,使它们返回超类中的某个(新增)字段 ,然后销毁子类。
建立子类的目的,是为了增加新特性或变化其行为。有一种变化行为被称为"常量函数",它们会返回一个硬编码的值。这东西有其用途:你可以让不同的子类中的同一个访问函数返回不同的值。你可以在超类中将访问函数声明为抽象函数,并在不同的子类中让它返回不同的值。
尽管常量函数有其用途,但若子类中只有常量函数,实在没有足够的存在价值。你可以在超类中设计一个与常量函数返回值对应的字段,从而完全去除这样的子类。如此一来就可以避免因继承而带来的额外复杂性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值