Effective Java 中文版之学习 第1条:考虑用静态工厂方法代替构造器

Effective Java 中文版之学习 第1条:考虑用静态工厂方法代替构造器

对于类而言为了让客户端获取自身的一个实例,最常用的方法就是提供一个公有的构造器。还有一种方法就是,类可以提供一个公有的静态工厂方法(static factory method),它只是返回类的实例的静态方法。下面是一个来自Boolean(基本数据类型boolean的包装类)的简单示例,这个方法将boolean基本类型值转换成了一个Boolean对象引用:

public static Boolean valueOf(boolean b){

return b ? Boolean.TRUE : Booean.FALSE;

}

注意:静态工厂方法模式与设计模式中的工厂方法模式不同,本条目中所指的静态工厂方法并不直接对应于设计    模式中的工厂方法。

类可以通过静态方法提供它的客户端,而不是通过构造器。提供静态方法而不是公有的构造器,这样做有几大优势。

静态工厂方法与构造器不同的第一大优势在于,它有名称。如果构造器的参数本身没有确切的描述正在返回的对象,那么具有适当名称的静态工厂会更容易使用,产生的客户端代码也更容易阅读。例如构造器BigInteger (int,int,Random)返回的Random可能为素数,如果用名为BigInteger.probablePrime的静态方法来表示,显然更为清楚。

当一个类需要多个带有相同签名的构造器时,就用静态工厂方法代替构造器,并且慎重的选择名称以便突出它们之间的区别。


静态工厂方法与构造器不同的第二大优势在于,不必每次调用他们的时候否创建一个新的对象。如果程序经常请求创建相同的对象,并且创建对象的代价很高,则这项技术可以极大地提高性能。

静态工厂方法能够为重复的调用返回相同的对象,这样有助于类总能严格控制在某些时刻哪些实例应该存在。


静态工厂方法与构造器不同地第三大优势在于,它们可以返回原返回类型的任何子类型的对象。这样我们在选择返回对象的类时就有了更大的灵活性。

这种灵活性的一种应用是,API可以返回对象,同时又不会是对象的类变为公有的。以这种方式隐藏实现类会使API变得非常简洁。

公有的静态方法返回的对象的类不仅可以是非公有的,而且该类还可以随着每次调用发生变化,这取决于静态工厂中的参数值。

静态工厂方法的第四大优势在于,在创建参数化类型实例的时候,他们使代码变得更加简洁。遗憾的是,在调用参数化类的构造器时,即使类型参数很明显,也必须指明。这通常要求你提供两次类型的参数:

Map> m = new HashMap>();

假设HashMap提供了提供了这个静态工厂:

public static HashMap  newInstance() {

return new HashMap();

}

你就可以用下面的代码代替上面这段繁琐的声明:

Map> m = HashMap.getInstance();


静态工厂方法的主要缺点在于,类如果不含公有的或者受保护的构造器,就不能被子类化。对于公有的静态工厂所返回的非公有类,也同样如此。

静态工厂方法的第二个缺点在于,他们与其他的静态方法实景导航没有任何区别。在API文档中他们没有像构造器那样在API文档中明确标识出来,因此,对于提供静态工厂方法而不是构造器的类来说,要想查明如何实例化一个类,这是非常困难的。Javadoc工具总有一天会注意到静态工厂方法。同时,你通过类或者接口注释中关注静态工厂,并遵守标准的命名习惯,也可以弥补这一劣势。下面是静态工厂方法中的一些惯用名称:

valueOf:不太严格地讲,该方法返回的实例与它的参数具有相同的值。这样的静态工厂方法实际是类型转换的         方法。

of:valueOf的一种更为简洁的替代。

getInstance:返回的实例是通过方法的参数来描述的,但是不能够说与参数具有同样的值。对于Singleton来       说,该方法没有参数,并返回唯一的实例。

newInstance:像getInstance一样,但newInstance能够确保返回的每个实例都与所有其他实例不同。

getType:像getInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法中所返回的对  象类型。

newType:向newInstance一样,但是在工厂方法处于不同类中的时候使用。Type表示工厂方法中所返回的对

  象类型。


总之,静态工厂方法和公有构造器都各有用处,我们需要理解他们各自的长处。静态工厂方法通常更加适合,因此切忌第一反应就是提供公有的构造器,而不先考虑静态工厂。

你可能感兴趣的:(阅读Effective,Java,中文版)