一、用静态工厂方法替代构造器
Boolean(基本类型boolean的装箱类)的简单示例。这个方法将boolean基本类型值转换成了一个Boolean对象引用:
public final class Boolean implements java.io.Serializable,
Comparable<Boolean>
{
//对应于原始值true的Boolean对象。
public static final Boolean TRUE = new Boolean(true);
//对应于原始值false的Boolean对象。
public static final Boolean FALSE = new Boolean(false);
//分配一个代表value参数的Boolean对象。
//注意:很少适合使用此构造函数。除非需要新实例,否则通常使用静态工厂value0f(boolean)是更好的选择。
//它可能会产生明显更好的时空性能。
//参数:value — Boolean .
public Boolean(boolean value) {
this.value = value;
}
//返回表示指定boolean值的Boolean实例。如果指定的boolean值为true,则此方法返回Boolean.TRUE ;
//Boolean.TRUE为true。如果为false,则此方法返回Boolean.FALSE。如果不需要新的Boolean实例,
//则通常应优先于构造方法Boolean(boolean)此方法,因为此方法可能会产生明显更好的时空性能。
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
}
1.1-静态工厂的优势
- 它们有名称,如果构造器的参数本身没有确切地描述正被返回的对象,那么具有适当名称的静态工厂会更容易使用,产生的客户端代码也更易于阅读。例如:构造器BigInteger ( int,int,Random)返回的BigInteger可能为素数,如果用名为BigInteger.probablePrime的静态工厂方法来表示,显然更为清楚。
不必在每次调用它们的时候都创建一个新对象。
public static void main(String[] args) {
Boolean b1 = Boolean.valueOf(true);
Boolean b2 = Boolean.valueOf(true);
System.out.println(b1 = b2);
}
//运行结果为true,b1和b2是同一个对象的应用
它们可以返回原返回类型的任何子类型的对象。这样我们在选择返回对象的类时就有了更大的灵活性。
- 所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值。只要是已声明的返回类型的子类型,都是允许的。返回对象的类也可能随着发行版本的不同而不同。
方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在。这种灵活的静态工厂方法构成了服务提供者框架(Service ProviderFramework)的基础,例如JDBC(Java数据库连接)API。服务提供者框架是指这样一个系统:多个服务提供者实现一个服务,系统为服务提供者的客户端提供多个实现,并把它们从多个实现中解耦出来。
- 服务提供者框架中有三个重要的组件:
- 服务接口(Service Interface),这是提供者实现的;
- 提供者注册API ( Provider Registration API),这是提供者用来注册实现的;
- 服务访问API (Service Access API),这是客户端用来获取服务的实例。
- 第四个组件,服务提供者接口(Service Provider Interface)是可选的,它表示产生服务接口之实例的工厂对象。如果没有服务提供者接口,实现就通过反射方式
- 对于JDBC来说,Connection就是其服务接口的一部分,DriverManager.registerDriver是提供者注册API, DriverManager.getConnection是服务访问API,Driver是服务提供者接口。
1.2-静态工厂的缺点
- 服务提供者框架中有三个重要的组件:
类如果不含公有的或者受保护的构造器,就不能被子类化。
程序员很难发现它们。在API文档中,它们没有像构造器那样在API文档中明确标识出来,因此,对于提供了静态工厂方法而不是构造器的类来说,要想查明如何实例化一个类是非常困难的。
二、遇到多个构造器参数时要考虑使用构建器
创建对象我们可以使用构造器和JavaBean的方式,还有第三种替代方法,它既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。这就是建造者(Builder)模式形式。它不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调汭无参的build方法来生成通常是不可变的对象。这个builder通常是它构建的类的静态成员类(详见第24条)。下面就是它的示例: ```java public class GirlFriend {
private String name; private int age; private int height;
public static class Build{
private String name;
private int age;
private int height;
public Build(String name){
this.name = name;
}
public Build setAge(int age){
this.age = age;
return this;
}
public Build setHeight(int height){
this.height = height;
return this;
}
public GirlFriend build(){
return new GirlFriend(this);
}
}
@Override public String toString() {
return "GirlFriend{" + "name='" + name + '\'' + ", age=" + age + ", height=" + height + '}';
}
private GirlFriend(Build build){
this.name = build.name; this.age = build.age; this.height = build.height;
}
public static void main(String[] args) {
GirlFriend build = new GirlFriend.Build("杨颖").setAge(18).build(); System.out.println(build.toString());
} } //输出:GirlFriend{name=’杨颖’, age=18, height=0}
```