《Effective Java》读书笔记 Item 1:考虑静态工厂方法,而不是构造器
众所周知,要想能获取一个类的实例,该类得要提供一个public的构造器。但是《Effective Java》书中说还有一个方法,那就是提供静态工厂方法(static factory method),该方法时静态,同时可以根据参数返回一个类的实例。这里的静态工厂方法(static factory method)和设计模式里的工厂方法(factory method)是不一样的,我觉得工厂方法注重的是多态。
使用静态工厂方法有利也有弊。
优点:
不像构造器那样,静态工厂方法拥有名字
静态工厂方法是有名称的,这样就有了“可读性”,看到方法的名称就能知道能返回什么样的实例。而对于构造器,通过提供参数,但是有时会让人很迷惑,因为有时是因为传递的参数之不同而返回特定的实例,书中举的例子是BigInteger(int, int, Random)这个构造器,如果想要返回一个素数,那么你就得传入合适的参数进去,但是如果BigInteget中有个静态方法是probablePrime,那么当开发者一看名字就很明白了,明白这个方法返回的是什么实例。有时一个类会有几个构造器,每个构造器的参数个数相差一点点,或者是参数个数相等,但是各个参数的意义不同,有时是参数个数不等,这些情况下,当使用该类的开发人员在用构造器实例化时,会很苦恼,得去看文档,知道每个参数的意义才行。
我觉得这一点是很实用的,在平时写代码时,我觉得得用上。
不像构造器那样,每次调用都要创建对象
Boolean.valueOf(boolean)这个方法正体现了这一点,通过阅读源代码,可以发现在Boolean类里有TRUE和FALSE这两个静态字段。valueOf方法只是判断传来的参数值然后返回合适的对象(TRUE或FALSE),也就是说这两个对象只是在Boolean类加载时创建,以后如果需要用到,就不要再重新创建,直接返回就行了。如果创建某个对象的代价相当可观,那么这个方法的优点就很明显了。不过的确是有不少情况,我们不需要重复地创建对象。
通过静态工厂方法,我们还可以在每次调用时都返回同一个对象。singleton模式就是例子。
不像构造器那样,静态工厂方法可以返回类型的某个子类型
静态工厂方法可以减少冗长的创建参数化类型时的代码
当使用构造器创建参数类型时,我们要这样做:
Map<String, List<String>> m = new HashMap<String, List<String>>();
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
Map<String, List<String>> m = HashMap.newInstance();
缺点
一个类在仅提供静态工厂方法,同时没有公共或受保护的构造器时,此类是没法被子类化的
在Collections Framework里就有这样的例子。不过这也算是因祸得福吧,这样我们可以尽量去通过组合(composition),而不是去通过继承(inheritance)来解决某些问题。