Replace Multiple Constructors with Creation Methods (10分)

  • 主题发起人 wind_jackyer
  • 开始时间
W

wind_jackyer

Unregistered / Unconfirmed
GUEST, unregistred user!
动机
某些语言允许你用自己喜欢的任何方式为自己的构造子命名,而不用管类的名字。另一些
语言(例如C++和Java)则不允许这样做:每个构造子都必须按照所属的类的名字来命名。
如果只有一个构造子,不成问题;但是如果拥有多个构造子,程序员就必须去了解构造子
期望的参数、观察构造子的代码,这样才能正确选择自己要使用的构造子。这有什么毛病
?毛病太多了。多个构造子根本无法有效描述意图。拥有的构造子越多,程序员就越容易
选择错误。而且,程序员不得不去选择使用哪个构造子,这降低了开发的速度,而且调用
构造子的代码经常不能有效的与构造出来的对象交流。
如果你觉得这听起来很糟糕,还有更糟糕的呢。随着系统日趋成熟,程序员们经常会加入
越来越多的构造子,而不去检查以前的构造子是否仍在使用。不再使用的构造子仍然留在
类中,这增加了类的静态负载,只会让类变得愈加臃肿而复杂。成熟的软件系统中往往充
斥着这种“死构造子”,因为程序员没有快速而简单的途径来识别某个构造子是否仍被调
用:IDE帮不了他们,判断某个方法确切的调用者所需的搜索语句又实在太麻烦。另一方面
,如果对象创建调用主要通过一个特定名称的方法来进行,例如createTermLoad()或者
createRevolver(),找到这些方法所有的调用者是轻而易举的。
那么,我们的同行们通常把创建对象的方法叫做什么?许多人都会回答“工厂方法
(Factory Method)”,这是因为那本经典著作《设计模式》[GoF]这样称呼一个创建型
模式。但是,所有创建对象的方法真的都是工厂方法吗?如果给“工厂方法”这个术语
一个更宽的定义:只要创建对象的方法都叫工厂方法,那么答案肯定是“Yes”。但是按
照这个创建型模式(Factory Method模式)的作者撰写它的方式来看,很明显并非所有创
建对象的方法都能提供真正的工厂方法所提供的那种松耦合。因此,为了在讨论与对象创
建相关的设计和重构时保证大家的清醒,我用“创建方法(Creation Method)”这个术语
来表示“一个创建对象的方法”。也就是说:工厂方法都是创建方法,但相反则未必。这
还意味着:在任何Martin Fowler或Joshua Bloch使用“工厂方法”这个术语(分别在他们
精彩的书《Refactoring》[Fowler]和《Effective Java》[Bloch]中)时,你都可以代之
以“创建方法”。
交流
重复
简化

多个构造子不是一种好的交流形式——很明显,通过能揭示意图的创建方法提供对实例的
访问,这是一种好的交流形式。
没有直接的重复,只是有许多看上去几乎完全一样的构造子。
指出应该调用哪个构造子并不是一件容易的事。通过能揭示意图的创建方法来构造不同类
型的对象,这个问题就简单多了。

过程
1. 识别出拥有多个构造子的类。这些构造子通常有一大堆参数,而这就让开发者
需要获得一个实例的时候更加迷惑了。
2. 识别出catch-all构造子,或者用Chain Constructor(见第8期《非程序员》)
创建一个catch-all构造子。如果catch-all构造子的可见性是public,将它改为private或
protected。
3. 针对每个构造子所能构造的那种对象,创建一个能够揭示意图的创建方法。测试
,确保每个创建方法都返回正确的对象,确定每个创建方法都被客户代码调用到了(如果
某个创建方法没有使用者,将它删掉;到需要它的时候再放回来)。
4. 把所有对构造子的调用都换成对相应创建方法的调用。这需要费些力气,但是可
以使客户代码的易读性大大提高。
 
顶部