Change Value to Reference 将值对象改为引用对象
你从一个类衍生出许多彼此相等的实例,希望将它们替换为同一个对象。将这个值对象变成引用对象。
动机
在许多系统中,你都可以对对象做一个有用的分类:引用对象和值对象。前者就像“客户”、“账户”这样的东西,每个对象都代表真实世界中的一个实物,你可以直接以相等操作符(==,用来检验对象同一性)检查两个对象是杏相等。后者则是像“日期”、“钱”这样的东西,它们完全由其所含的数据值来定义,你并不在意 副本的存在,系统中或许存在成百上千个内容为“1/1/2000”的“日期”对象。当然,你也需要知道两个值对象是否相等,所以你需要覆写equals()(以及hashCode())。
要在引用对象和值对象之间做选择有时并不容易。有时候,你会从一个简单的值对象开始,在其中保存少童不可修改的数据。而后,你可能会希望给这个对象加入一些可修改数据,并确保对任何一个对象的修改都能影响到所有引用此一对象的地方。这时候你就需要将这个对象变成一个引用对象。
做法
- 使用Replace Constructor with Factory Method。
- 编译,测试。
- 决定由什么对象负责提供访问新对象的途径。
- 可能是一个静态字典或一个注册表对象,
- 你也可以使用多个对象作为新对象的访问点。
- 决定这些引用对象应该预先创建好,或是应该动态创建。
- 如果这些引用对象是预先创建好的,而你必须从内存中将它们读取出来,那么就得确保它们在被需要的时候能够被及时加载。
- 修改工厂函数,令它返回引用对象。
- 如果对象是预先创建好的,你就需要考虑:万一有人索求一个其实并不存在的对象,要如何处理措误?
- 你可能希望对工厂函数使用Rename Method,使其传达这样的信息:它返回的是一个既存对象。
- 编译,测试。
要把一个引用对象变成值对象,关键动作是:检查它是否不可变。如果不是,我就不能使用本项重构,因为可变的值对象会造成烦人的别名问题。