Effective Java学习笔记之第1条 考虑用静态工厂方法代替构造器
第1条 考虑用静态工厂方法代替构造器
对于类而言,为了让客户端获取自身都一个实例,最常用的方法是提供一个公有地构造器。还有一个方法:提供一个公有的静态工厂方法(static factory method)。
示例1: 将boolean基本类型值转换成一个Boolean对象引用。
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
静态工厂方法都优势:
一。 静态方法都有名称。例如:构造器BigInteger(int, int, Random)返回的BigInteger可能为素数,如果用名为BigInteger.protablePrime的静态工厂方法来表示,显然更为清楚。
当一个类需要多个带有相同签名的构造器时,就用静态工厂方法代替构造器,并且慎重的选择名称以便突出它们之间都区别。
二。 不必在每次调用它们都是很都创建一个新的对象。这使得不可变对象可以使用预先构建好的实例,或者将构建好的实例缓存起来,进行重复利用。Boolean.valueOf(boolean)方法说明了这项技术。这种方法类似于Flyweight模式。
如果程序经常请求创建相同的对象,并且创建对象都带价很高,则这项技术可以极大的提升性能。
三。静态工厂方法可以返回原返回类型都任何子类型都对象。 这种灵活性的一种应用是,API可以返回对象,同时又不会使对象都类变成公有的。这项技术适用于基于接口的框架(interface-based framework), 因为在这种框架中,接口为静态工厂方法提供了自然返回类型。接口不能有静态方法,因此按照惯例,接口Type的静态工厂方法被放在一个名为Types的不可实例化都类中。
例如: Java Collections Framework的集合接口有32个便利实现,分别提供了不可修改的集合,同步集合等等。几乎所有这些实现都通过静态工厂方法在一个不可实例化都类(java.util.Collections)中导出,所有返回对象都的类都是非公有的。
使用这种静态工厂方法时,甚至要求客户端通过接口来引用被返回的对象,而不是通过它的实现类拉引用被返回的对象,这是一种良好的习惯。
四。在创建参数化类型实例都时候,它们使代码变得更加简洁。但通常要求连续两次提供类型参数。
Map<String, List<String>> m = new HashMap<String, List<String>>();
但是有了静态工厂方法,编译器可以替你找到类型参数,这被称作类型推导(type inference). 例如,假设HashMap提供了这个静态工厂方法:
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
你就可以用下面这句简洁地代码代替上面都声明:
Map<String, List<String>> m = HashMap.newInstance();
静态工厂方法都主要缺点:
一。类如果不含公有的或者受保护的构造器,就不能被子类化。这样也会因祸得福,因为它鼓励复合,而不是继承。
二。它与其它静态方法实际上没有任何区别。
下面是静态工厂方法都一下惯用名称:
valueOf --该方法返回的实例与它的参数具有相同的值。这样的静态工厂方法实际上就是类型转换方法。
of -- valueOf的一种更为简洁地替代。
getInstance -- 返回的实例是通过方法都参数来描述得,但不能说与参数具有相同的值。对于Singleton来说,该方法没有参数,并返回唯一的实例。
newInstace -- 想getInstance一样,但newInstance能够确保返回的每个实例都与所有其他实例不同。
getType -- 想getInstance一样, 但是在工厂方法处于不同的类中使用。Type表示工厂方法所返回的对象类型。
newType -- 像newInstance一样,但是在工厂方法处于不同的类中使用。Type表示工厂方法所返回的对象类型。
简而言之,静态工厂方法和公有构造器都各有用处,我们需要理解他们各自都长处。静态工厂通常更加合适,因此切忌第一反应就是提供公有的构造器,而不先考虑静态工厂。