美文网首页
1.考虑用静态工厂方法代替构造器

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

作者: 哲学与豆包 | 来源:发表于2018-01-31 17:37 被阅读0次

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

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

    下面的例子中 无论是戴眼镜的人还是不戴眼镜的人,他们都是通过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");
    

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

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

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

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

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

    总结

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

    相关文章

      网友评论

          本文标题:1.考虑用静态工厂方法代替构造器

          本文链接:https://www.haomeiwen.com/subject/czhkzxtx.html