Effective Java – Item 1 静态工厂

item1 · 静态工厂

静态工厂不是设计模式中的工厂方法

例子

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

优点

  • 静态工厂有名字

        /**
         * Constructs a newly allocated {@code Integer} object that
         * represents the specified {@code int} value.
         *
         * @param   value   the value to be represented by the
         *                  {@code Integer} object.
         *
         * @deprecated
         * It is rarely appropriate to use this constructor. The static factory
         * {@link #valueOf(int)} is generally a better choice, as it is
         * likely to yield significantly better space and time performance.
         */
        @Deprecated(since="9")
        public Integer(int value) {
            this.value = value;
        }
    
    • 使用 Integer.valueOf(123) 比使用 new Integer(123) 更为直观
    • 源代码中的更好的空间和时间可以见 Integer.vauleOf(int) 的实现(参见下一条)
        /**
         * Returns an {@code Integer} instance representing the specified
         * {@code int} value.  If a new {@code Integer} instance is not
         * required, this method should generally be used in preference to
         * the constructor {@link #Integer(int)}, as this method is likely
         * to yield significantly better space and time performance by
         * caching frequently requested values.
         *
         * This method will always cache values in the range -128 to 127,
         * inclusive, and may cache other values outside of this range.
         *
         * @param  i an {@code int} value.
         * @return an {@code Integer} instance representing {@code i}.
         * @since  1.5
         */
        @HotSpotIntrinsicCandidate
        public static Integer valueOf(int i) {
            if (i >= IntegerCache.low && i <= IntegerCache.high)
                return IntegerCache.cache[i + (-IntegerCache.low)];
            return new Integer(i);
        }
    
  • 不必每次调用都创建一个新对象

    • Boolean 示例中 valueOf 无需每次创建新对象,因为只存在两种情况
    • Integer.valueOf(int) 中使用的 IntegerCache 对值为 -128~127 的 Integer 对象进行缓存
      Integer a = 1000, b = 1000;  
      System.out.println(a == b); // false  
      Integer c = 100, d = 100;  
      System.out.println(c == d); // true
    
  • 可以返回原返回类型的任何子类型对象

    interface Parent {
        static Parent getChild1(){
                return new Child1();
        }
        static Parent getChild2(){
            return new Child2();
        }
    }
    
    class Child1 implements Parent {}
    class Child2 implements Parent {}
    
    • Java 8 之后可以支持接口有静态方法(如上)
    • 另一例:Java Collections Framework 有45个工具实现,分别提供了不可修改的集合、同步集合,等等。
  • 随每次调用而发生变化

    interface Parent {
        static Parent getChild(int i) {
            return i == 1 ? new Child1() : new Child2();
        }
    }
    
    class Child1 implements Parent {}
    class Child2 implements Parent {}
    
  • 返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在

    • 服务提供者框架的基础
    • 例:JDBC
      • 服务接口(Service Interface) Connection
      • 提供者注册API (Provider Registration API) DriverManager.registerDriver
      • 服务访问API(Service Access API) DriverManager.getConnection
      • 不同数据库的 Connection 的具体实现是不一样的,通过 registerDriver 注册数据库的连接方法到JDBC上,通过 getConnection 获得可以使用的 Connection

缺点

  • 类如果不包含公有的或者受保护的构造器,就不能被子类实例化

    public class Collections {
        // Suppresses default constructor, ensuring non-instantiability.
        private Collections() {
        }
    }
    
  • 不容易识别出静态工厂

    • 在API文档中没有像构造器那样明确标识出来

    • 通过在类或者接口注释中关注静态工厂,并遵守标准的命名习惯

      • from —— 类型转换方法

        Date d = Date.from(instant);
        
      • of —— 聚合方法,带有多个参数

        Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
        
      • valueOf —— 比 from 和 of 更封锁的一种替代方法

        BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
        
        
      • instance 或 getInstance —— 返回的实例时通过方法的(如有)参数来描述的,但是不能说与参数具有同样的值

        StackWalker luke = StackWalker.getInstance(options);
        
        
      • create 或 newInstance —— 像instance或者getInstance一样,区别在于每次调用都返回一个新的实例

        Object newArray = Array.newInstance(classObject, arrayLen);
        
        
      • getType —— 像getInstance一样,但是在工厂方法处于不同的类中的时候使用。Type表示工厂方法所返回的对象类型

        FileStore fs = Files.getFileStore(path);
        
        
      • newType —— 像newInstance一样,但是在工厂方法处于不同的类中的时候使用

        BufferedReader br = Files.newBufferedReader(path);
        
        
      • type —— getType和newType的简版

        List<Complaint> litany = Collections.list(legacyLitany);
        
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值