Encapsulate Collection 封装集合

有个函数返回一个集合。让这个函数返回该集合的一个只读副本,并在这个类中提供添加/移除集合元素的函数。

动机

我们常常会在一个类中使用集合(collection,可能是array、list、set或vector)来保存一组实例。这样的类通常也会提供针对该集合的取值/设值函数。

但是,集合的处理方式应该和其他种类的数据略有不同。取值函数不该返回集合自身,因为这会让用户得以修改集合内容而集合拥有者却一无所悉。这也会对用户暴露过多对象内部数据结构的信息。如果一个取值函数确实需要返回多个值,它应该避免用户直接操作对象内所保存的集合,并隐藏对象内与用户无关的数据结构。至于如何做到这一点,视你使用的Java版本不同而有所不同。

另外,不应该为这整个集合提供一个设值函数,但应该提供用以为集合添加/移除元素的函数。这样,集合拥有者(对象)就可以控制集合元素的添加和移除。

如果你做到以上几点,集合就被很好地封装起来了,这便可以降低集合拥有者和用户之间的耦合度。

做法

  • 加入为集合添加/移除元素的函数。
  • 将保存集合的字段初始化为一个空集合。
  • 编译。
  • 找出集合设值函数的所有调用者。你可以修改那个设值函数,让它使用上述新建立的“添加/移除元素”函数;也可以直接修改调用端,改让它们调用上述新建立的“添加/移除元素”函数。
    • 两种情况下需要用到集合设值函数:
      1. 集合为空时;
      2. 准备将原有集合替换为另一个集合时。
    • 你或许会想运用Rename Method为集合设值函数改名:从setXxx()改为initializeXxx()或replaceXxx ()。
  • 编译,测试。
  • 找出所有“通过取值函数获得集合并修改其内容”的函数。逐一修改这些函数,让它们改用添加/移除函数。毎次修改后,编译并测试。
  • 修改完上述所有“通过取值函数获得集合并修改集合内容”的函数后,修改取值函数自身,使它返回该集合的一个只读副本。
    • 在Java2中,你可以使用Collection.unmodifiableXxx()得到该集合的只读副本。
    • 在Java1.1中,你应该返回集合的一份副本。
  • 编译,测试。
  • 找出取值函数的所有用户,从中找出应该存在于集合所属对象内的代码。运用Extract Method和Move Method将这些代码移到宿主对象去。
    • 如果你使用Java2,那么本项重构到此为止。如杲你使用Java1.1,那么用户也许会喜欢使用枚举。为了提供这个枚举,你应该像如下这样做。
  • 修改现有取值函数的名字,然后添加一个新取值函数,使其返回一个枚举。找出旧取值函数的所有被使用点,将它们都改为使用新取值函数。
  • 如果这一步跨度太大,你可以先使用Rename Method修改原取值函数的名称;再建立一个新取值函数用以返回枚举;最后再修改所有调用者,使其调用新取值函数。
  • 编译,测试。

results matching ""

    No results matching ""