Effective Java 1:考虑使用静态工厂方法代替构造器

最近在看Effective Java,第一条是考虑使用静态工厂方法代替构造器。

优点

  1. 静态工厂方法与构造方法不同的是它们有方法名称
  2. 不必每次调用它们的时候创建一个新的对象
  3. 它们的返回类型可以是任何子类型对象

第一条静态方法名字可以比较随意的命名,不像构造方法,必须要和类名一样。

对于第二条,最常见的例子就是单利模式,调用单利模式的方法,每次返回的对象都是同一个,不像调用构造方法,每次都是返回一个新的对象。

对于第三条,最常见的例子就是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方法来调用,这个场景就是这篇文档所讲的使用静态工厂方法代替构造器。

你可能感兴趣的:(Android,设计模式,蓝牙配对)