最近在看Effective Java,第一条是考虑使用静态工厂方法代替构造器。
第一条静态方法名字可以比较随意的命名,不像构造方法,必须要和类名一样。
对于第二条,最常见的例子就是单利模式,调用单利模式的方法,每次返回的对象都是同一个,不像调用构造方法,每次都是返回一个新的对象。
对于第三条,最常见的例子就是Java中Arrays提供一个asList的方法。
class Arrays{
public static List asList(T... a) {
return new ArrayList<>(a);
}
}
如上所示,在asList方法中,返回的是List对象,大家都知道List是一个接口,但是返回的实现者是具体那一个,对于调用者来说,是不可见的,调用者只需要按照List接口中申明的方法调用即可。
注意:上面的返回的是new ArrayList(),这个ArrayList,不是我们常见的ArrayList,这个是Arrays的一个内部类。
对于第一条,是对应优点中的第三条,意思是说,如果要是使用某个子类实例化,那么这个子类必须要有pubilc或protected的构造方法。
对应第二条是说,因为是静态方法,那么在文档中显示的样式和构造方法显示的样式是不一样的,在文档中也只是当做一个普通的方法看待,如果需要引起调用者的注意,需要额外添加一些提醒。
常用的静态方法构造名称有如下:
- valueOf:不太严格的讲,该方法返回的实例与它的参数有相同的值,这样的静态方法,实际上就是做类型的转换方法。
- of:和上面一样,感觉和枚举优点类似
- getInstance:返回的实例是根据参数描述来的,一般用在单利模式中比较多
- newInstance:和上面的getInstance差不多,但是使用的是new,所以要保证每次返回的对象是不一样的
- getType:和getInstance一样,但是在工厂方法处于不同类中的时候使用,Type表示工厂方法返回对象的类型
- newType:和newInstance一样,但是在工厂方法中处于不同类中的时候使用,Type表示工厂方法返回对象类型。
下面附上Android中Bitmap的源码作为示例:
package android.graphics;
public final class Bitmap implements Parcelable {
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
boolean filter) {
}
public static Bitmap createBitmap(Bitmap src) {
return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
}
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
return createBitmap(source, x, y, width, height, null, false);
}
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter) {
}
public static Bitmap createBitmap(int width, int height, Config config) {
return createBitmap(width, height, config, true);
}
public static Bitmap createBitmap(DisplayMetrics display, int width,
int height, Config config) {
return createBitmap(display, width, height, config, true);
}
private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
return createBitmap(null, width, height, config, hasAlpha);
}
private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
Config config, boolean hasAlpha) {
return bm;
}
public static Bitmap createBitmap(int colors[], int offset, int stride,
int width, int height, Config config) {
return createBitmap(null, colors, offset, stride, width, height, config);
}
public static Bitmap createBitmap(DisplayMetrics display, int colors[],
int offset, int stride, int width, int height, Config config) {
return bm;
}
public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
return createBitmap(null, colors, 0, width, width, height, config);
}
public static Bitmap createBitmap(DisplayMetrics display, int colors[],
int width, int height, Config config) {
return createBitmap(display, colors, 0, width, width, height, config);
}
Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
boolean isMutable, boolean requestPremultiplied,
byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
}
}
代码中很多详细代码都已经去掉,只留下了一些方法的目录,Bitmap的构造方式是默认的访问权限的,App中是无法new出来的,只能通过静态的createBitmap方法来调用,这个场景就是这篇文档所讲的使用静态工厂方法代替构造器。