1.考虑用静态工厂方法代替构造器

静态方法与构造器不同的第一大优势在于,它们有名称

对于类的构造器来说他们的名字一定是一样的

下面的例子中 无论是戴眼镜的人还是不戴眼镜的人,他们都是通过NEW的时候传进来的参数.但是这样很不明确,构造器并没有完美的表达这个意思,可读性很差.

   public class person {
    private String name;
    private int sex;
    private boolean glasses;

    // 普通的人
    public person(String name, int sex) {
        this.name = name;
        this.sex = sex;
    }

    // 带眼镜的人
    public person(String name, int sex, boolean glasses) {
        this.name = name;
        this.sex = sex;
        this.glasses = glasses;
    }
}

我们来看看作者举的一个正面的例子

    // BigInteger构造方法 这个方法可能会返回素数 语义表达不明确
    public BigInteger(int bitLength, int certainty, Random rnd) {
        BigInteger prime;

        if (bitLength < 2)
            throw new ArithmeticException("bitLength < 2");
        prime = (bitLength < SMALL_PRIME_THRESHOLD
                                ? smallPrime(bitLength, certainty, rnd)
                                : largePrime(bitLength, certainty, rnd));
        signum = 1;
        mag = prime.mag;
    }
  
    //所以在最后BigInteger 提供了一个静态方法 这个方法名清晰的告诉了我们可能是返回素数的
    public static BigInteger probablePrime(int bitLength, Random rnd) {
        if (bitLength < 2)
            throw new ArithmeticException("bitLength < 2");

        return (bitLength < SMALL_PRIME_THRESHOLD ?
                smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
                largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
    }

静态工厂方法与构造器不同的第二大优势在于,不必在每次调用它们的时候都创建一个新的对象

我们知道既然你调用了构造方法那肯定是会新建一个对象的,但是用静态工厂方法就不一定了,我们可以先将对象缓存起来

这个例子是Boolean类的

    public static final Boolean TRUE = new Boolean(true);

    public static final Boolean FALSE = new Boolean(false);

    // 直接返回了保存好的对象
    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }

静态工厂方法与构造器不同的第三大优势在于,他们可以返回原返回类型的任何子类型的对象

RegularEnumSet 和 JumboEnumSet 全部都是继承自EnumSet

   public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
       Enum<?>[] universe = getUniverse(elementType);
       if (universe == null)
           throw new ClassCastException(elementType + " not an enum");
       // 返回一个EnumSet子类
       if (universe.length <= 64)
           return new RegularEnumSet<>(elementType, universe);
       else
           return new JumboEnumSet<>(elementType, universe);
   }

本段落还有一个例子, 现在我并没有看懂,也并没有懂适配器模式,所有以后再来补充

静态工厂第四大优在于,在创建参数化类型实例的时候,它们使代码变得更加简洁

这一点现在已经不存在了,但还是举个例子

    // java1.7以前 即使泛型已经规定好了数据类型,但是你还是要写出来
    List<String>  list = new ArrayList<String>();

    // java1.7以后
    List<String> list = new ArrayList<>();

    // Guava Lists静态工厂方法 
    public static <E> ArrayList<E> newArrayList(E... elements) {
        checkNotNull(elements); 
        int capacity = computeArrayListCapacity(elements.length);
        ArrayList<E> list = new ArrayList<>(capacity);
        Collections.addAll(list, elements);
        return list;
    }

    //调用 通过静态方法工厂就不需要写出来了
    List<String> list = Lists.newArrayList("1");

静态工厂方法的主要缺点在于,类如果不含公有的或者受保护的构造器,就不能被子类化

如果构造器为私有的,通过静态方法来获得对象,那么该类是没有办法子类化的,也就是说无法继承.

静态工厂方法的第二个缺点在于,它们与其他的静态方法实际上没有任何区 别

本质上还是一个静态方法,但是实质上它用于创建对象,和普通静态方法差别很大,却没有有效的办法可以区分他们

作者的建议: 在类或接口注释中关注静态工厂,给静态工厂方法命名时遵守惯用的命名规范.

总结

简而言之,静态工厂方法和公有构造器都各有用处,我们需要理解它们各自的长处,静态工厂通常更加合适,因此切忌第一反应就是提供公有的构造器,而不先考虑静态工厂

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容