对于类而言,为了让客户端获取它自身的一个实例,最常用的方法是提供一个共有的构造器。还有一种方法:类可以提供一个共有的静态工厂方法,它只是一个返回类的实例等静态方法。下面是一个来自Boolean的简单示例。这个方法将boolean基本类型值转换成了一个Boolean对象引用:
|
|
类可以通过静态工厂方法来提供它的客户端,而不是通过构造器,这样做具有几大优势:
它们有名称
对于同一个对象,它们的构造函数的名称是一样的,如果构造器的参数本身没有确切的描述被正确返回的对象,那么具有适当名称的静态工厂会更容易使用,产生的客户端代码也会更容易阅读。
不必在每次调用它们的时候都创建一个心对象
这可以将构建好的实例缓存起来,进行重复使用,从而避免创建不必要的重复对象。例如
Boolean.valueOf(boolean)
,它从来不创建对象。更多的应用是在单例模式中,调用单例模式的方法,每次返回的对象都是同一个。它们可以返回原返回类型的任何子类型的对象
这样我们在选择返回对象的类时就有了更大的灵活性,最常见的例子就是Java中Arrays提供的asList方法:
123public static <T> List<T> asList(T... a) {return new ArrayList<>(a);}在上述方法中,返回的是List对象,但是List是一个接口,返回的实例是具体哪一个,对于调用者来说是不可见的。
注意:这里的ArrayList是Array的一个内部类。
这个主要根据传入工厂静态方法的参数来实现,只要是已声名的返回类型的子类型,都是可以的。这为我们选择返回对象的类型提供了灵活性。
在创建参数化实例类型的时候,使代码变得更加简洁
在低啊用参数化类的构造器时,即使类型参数很明显,也必须指明:
1Map<String, List<String>> m = new HashMap<String, List<String>>();随着参数类型变的越来越长,越来越复杂,这样就显得很冗长。但是可以通过静态工厂方法,编译器可以替你找到参数类型,这被称作类型推到。例如:
123public static <K, V> HashMap<K, V> newInstance() {return new HashMap<K, V>();}创建对象的时候只需要:
1Map<String, List<String>> m = HashMap.newInstance();
静态工厂方法的主要缺点在于:
类如果不含共有或者受保护的构造器,就不能被子类化。
这一点对应于优点中的第三条,如果要使用某个子类实例化,那么这个子类必须要有public或者protected的构造方法。
它们与其他的静态方法没有区别
地位不像构造函数一样很高。
常用的静态方法构造名称有如下:
- valueOf:不太严格的讲,该方法返回的实例与它的参数有相同的值,这样的静态方法,实际上就是做类型的转换方法。
- of:和上面一样,感觉和枚举优点类似
- getInstance:返回的实例是根据参数描述来的,一般用在单利模式中比较多
- newInstance:和上面的getInstance差不多,但是使用的是new,所以要保证每次返回的对象是不一样的
- getType:和getInstance一样,但是在工厂方法处于不同类中的时候使用,Type表示工厂方法返回对象的类型
- newType:和newInstance一样,但是在工厂方法中处于不同类中的时候使用,Type表示工厂方法返回对象类型。