• 2012-06-04

    代码之丑(十四)

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/216314257.html

    代码评审,我对一个TreeSet产生了兴趣。

    TreeSet configuration = new TreeSet();
    ...
    Handler handler = new Handler(configuration);

    “为什么要用TreeSet呢?”,我问道。
    “因为这是构造函数的参数决定的。”,有人回答。
    “可以打开源码看一下吗?”,对于这种处理,通常人们都会选择HashSet,好奇心驱使我要进一步专研一下这段代码。

    我看到了这个构造函数的声明:
    public Handler(TreeSet configuration) {
      ...
    }

    在我开始研究这个构造函数使用TreeSet的缘由之前,我看到了另外一个构造函数,或许它更能满足我的心理需求:
    public Handler(HashSet configuration) {
      ...
    }

    “为什么会有一个用到HashSet构造函数?它和用到TreeSet的有什么不同”,我继续追问。
    “它们是分别处理两种情况的,在不同的配置下起作用。”

    我终于知道为什么会有TreeSet,因为HashSet已经被人用了,为了支持另外一种情形,TreeSet被人从墙角了挖了出来。可是如果不深究代码,谁又能知道这其中的奥妙呢?显然,我们需要一个更具表达力的写法。

    之所以陷入这样的坑,根源在于构造函数,因为构造函数只能有一个名字。其实,这里只是要解决构造的问题,而面对这个问题,解决方式几乎再直白不过了:工厂方法。

    class HandlerFactory {
      public static Handler createTrivialHandler(Set configuration) {
        ...
      }

      public static Handler createFancyHandler(Set configuration) {
        ...
      }
    }

    这里,用两个名字上有更明确意义的函数替代之前的那两个需要强大理解力的构造函数。当然,这里的参数用了Set,连具体的类型都省了,真正的面向接口编程。

    事实上,如果一个类有多于一个的构造函数,都是值得考虑的。我曾写过一篇《构造函数沉思录》专门讨论这个问题。

    分享到:

    历史上的今天:

    别人的标准 2007-06-04
    引用地址: