对于类而言,为了让客户端获取它自身的一个实例,最常用的方法就是提供一个公有的构造器。
还有一种方法,名为静态工厂方法(不对应于设计模式中的工厂方法).
我们应该考虑用静态工厂方法代替构造器。
一个静态工厂方法创建对象的简单例子:1234567public static Person newInstance(){ Person person = new Person(); if (person==null) { throw new IllegalArgumentException("error"); } return person;}
优势:
- 它们有名称
- 不必在每次调用它们的时候创建一个新对象
- 它们可以返回原返回类型的任何子类型的对象
- 在创建参数化类型实例的时候,它们使代码变得更加简洁
缺点:
- 类如果不含公有的或者受保护的构造器,就不能被子例化
- 它们与其他的静态方法实际上没有任何区别
惯用名称:
valueOf
—— 不太严格地讲,该方法返回的实例与它的参数具有相同的值。这样的静态工厂方法实际上是类型转换方法of
—— valueOf的一种更为简洁的替代。在EnumSet中使用并流行起来getInstance
—— 返回的实例是通过方法的参数来描述的,但是不能够说与参数具有相同的值。对于Singleton来说,该方法没有参数,并返回唯一实例newInstance
—— 像getInstance一样,但newInstance能够确保返回的每个实例都与其他实例不同getType
—— 像getInstance一样,但是在工厂方法处于不同类中的时候使用。Type表示工厂方法所返回的对象类型newType
—— 像newInstance一样,但是在工厂方法中处于不同的类中的时候使用。Type表示工厂方法中所返回的对象类型
遇到多个构造器参数时要考虑用构建器
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。
对于多个参数的类,有以下较为常用的方法。
重叠构造器模式
|
|
重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且难以阅读。
JavaBean模式
|
|
因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保持一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来十分困难。与此相关的另一点不足在于,JavaBean模式阻止了把类变成不可变的可能,这就需要程序员付出额外的努力来确保它的线程安全。
构建器模式
|
|
构建器模式不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或静态工厂),得到一个builder对象。然后客户端在builder上调用类似与setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法生成不可变的对象。
参考资料: 【Effective Java】中文版第2版