zoukankan      html  css  js  c++  java
  • Effective Java —— 用私有构造器或枚举类型强化单例属性

    本文参考

    本篇文章参考自《Effective Java》第三版第三条"Enforce the singleton property with a private constructor or an enum type"

    原文的不足之处

    原文给的示例代码比较简单,提供的是一种饿汉式的单例模式

    // Singleton with public final field
    public class Elvis {
        public static final Elvis INSTANCE = new Elvis();
        private Elvis() { ... }
        public void leaveTheBuilding() { ... }
    }

    我们也可以将INSTANCE实例的pulice改为private,通过另一个静态方法获取实例

    // Singleton with static factory
    public class Elvis {
        private static final Elvis INSTANCE = new Elvis();
        private Elvis() { ... }
        public static Elvis getInstance() { return INSTANCE; }
        public void leaveTheBuilding() { ... }
    }

    构造器的private关键字修饰使得无法通过new关键字创建其它实例,final关键字的修饰使得INSTANCE总是包含相同的对象引用,这两种写法都能保证全局下仅有一个Elvis类的实例化对象

    因为饿汉模式下,全局的单例实例在类装载时就进行构建,可能由于初始化的太早,会造成资源的浪费,所以有另一种懒汉式的单例模式,但原文中未做介绍,因为它在多线程下存在实例重复构建的问题,若要解决这个问题,会加大文章篇幅,而且也不是第三条建议的重点,更多关于懒汉式的单例模式可以参考这篇文章:

    https://www.jianshu.com/p/eb30a388c5fc

     

    the best way to implement a singleton —— a single-element enum type

    Java的枚举类型是一个特殊的class,并继承了Enum<T>类,若Singleton必须扩展一个超类,而不是扩展Enum 时,则不宜使用如下方法

    public class Elvis {
      private Elvis() {
      }

      public static Elvis getInstance() {
        return Singleton.INSTANCE.getInstance();
      }

      /**
       *
    注意声明为private
       */
      private enum
    Singleton {
        INSTANCE;
        private Elvis singleton;
        /**
         *
    仅执行一次
         */
        Singleton() {
          singleton = new Elvis();
        }
        public Elvis getInstance() {
          return singleton;
        }
      }
    }

    因为Enum<T>类实现了Serializable接口,所以为INSTANCE自动提供了序列化机制,并且编译器会为枚举类型的实例自动添加 public static final 修饰,所以枚举类型的无参构造方法仅会被执行一次

    原文也指出这种方式能够应对复杂的序列化或者反射攻击的情形

    provides the serialization machinery for free, and provides an ironclad guarantee against multiple instantiation, even in the face of sophisticated serialization or reflection attacks.

  • 相关阅读:
    Day1-while and for/break and continue
    Day1-用户输入及字符串格式化输入
    Day1-python基础
    2-21-源码编译搭建LNMP环境
    2-20-使用apache搭建web网站
    2-19-mysql优化
    2-18-搭建mysql集群实现高可用
    2-17-MySQL读写分离-mysql-proxy
    2-16-2MySQL主从
    2-14-存储过程-触发器-事务
  • 原文地址:https://www.cnblogs.com/kuluo/p/12753327.html
Copyright © 2011-2022 走看看