zoukankan      html  css  js  c++  java
  • 枚举实现单例模式

    写在前面

    单例模式定义: 一个类 只能创建一个实例。

    使用一个对象来做就不用实例化多个对象!这就能减少我们空间和内存的开销~

    我们使用静态类.doSomething()和使用单例对象调用方法的效果是一样的啊。

    没错,效果就是一样的。使用静态类.doSomething()体现的是基于对象,而使用单例设计模式体现的是面向对象。

    编写单例模式的代码其实很简单,就分了三步:

    将构造函数私有化
    
    在类的内部创建实例
    
    提供获取唯一实例的方法
    

    常用的单例模式

    1. 饿汉式
    public class Liuge36 {
       
        // 1.构造函数私有化
        private Liuge36(){
    
        }
        // 2.在类的内部创建实例
        private static Liuge36 liuge36 = new Liuge36();
    
        // 3.提供获取实例的唯一方法
        public static Liuge36 getInstance(){
            return liuge36;
        }
    
    }
    

    一上来就创建对象了,如果该实例从始至终都没被使用过,则会造成内存浪费。

    1. 简单懒汉式 (在方法上加锁)
      既然说一上来就创建对象,如果没有用过会造成内存浪费:
      那么我们就设计用到的时候再创建对象!
    public class Liuge36 {
        // 1.将构造函数私有化
        private Liuge36(){
    
        }
        // 2.先不创建对象,等用到的时候 ,再开始创建
        private static Liuge36 liuge36 = null;
        
        /**
         * 3.调用获取实例的方法,说明要用到实例对象了
         * synchronized 加锁之后才能保证在多线程下代码可用,不加锁仅仅适用于单线程的情况
         */
        public static synchronized Liuge36 getInstance(){
    
            // 先判断对象是否为空,如果为空,先创建再返回出去
            if (liuge36 == null) {
                liuge36 = new Liuge36();
            }
            return liuge36;
    
        }
    }
    
    1. DCL双重检测加锁(进阶懒汉式)
      上面那种直接在方法上加锁的方式其实不够好,因为在方法上加了内置锁在多线程环境下性能会比较低下,所以我们可以将锁的范围缩小。
    public class Liuge36 {
        // 1.将构造函数私有化
        private Liuge36(){
    
        }
    
        /**
         * 利用静态变量liuge36来记录Liuge36的唯一实例
         *
         * volatile 关键字确保:当变量liuge36 被初始化成 Liuge36实例时,
         * 多个线程正确地处理liuge36变量
         *
         * volatile有内存屏障的功能!
         */
        private static volatile Liuge36 liuge36 = null;
    
        // 提供获取唯一实例的方法
        public static Liuge36 getInstance(){
            if (liuge36 == null){
    
                // 同步代码块 ,将锁的范围缩小,提高性能
                synchronized (Liuge36.class){
                    // 再次判断对象是否创建过
                    if (liuge36 == null){
                        liuge36 = new Liuge36();
                    }
                }
    
            }
            return liuge36;
        }
    }
    
    
    1. 静态内部类实现懒汉式
    public class Liuge36 {
        // 1.将构造函数私有化
        private Liuge36(){
    
        }
    
        /**
         * 使用静态内部类的方式实现懒加载
         * 初始化静态数据时,Java提供了的线程安全性保证。(所以不需要任何的同步)
         */
        private static class LazyHolder{
            // 创建单例对象
            private static final Liuge36 instance = new Liuge36();
        }
        // 提供获取实例的唯一方法
        public static Liuge36 getInstance(){
            return LazyHolder.instance;
        }
    
    }
    
    1. 枚举方式
      Joshua Bloch说“单元素的枚举类型已经成为实现Singleton的最佳方法
    public class Liuge36 {
        // 1.将构造函数私有化
        private Liuge36(){
    
        }
        // 2 定义一个静态枚举类
        static enum SingletonEnum{
            INSTANCE;
            private Liuge36 liuge36;
            // 私有化枚举的构造函数
    
            private SingletonEnum(){
                liuge36 = new Liuge36();
            }
    
            public Liuge36 getLiuge36(){
                return liuge36;
            }
        }
    
        // 3. 提供获取实例的唯一方法
        public static Liuge36 getInstance(){
            return SingletonEnum.INSTANCE.getLiuge36();
        }
    
        public static void main(String [] args){
            System.out.println(Liuge36.getInstance());
            System.out.println(Liuge36.getInstance());
            System.out.println(Liuge36.getInstance()==Liuge36.getInstance());
        }
    
    }
    

    总的来说单例模式写法有5种:

    饿汉式
    
    简单懒汉式(在方法加锁)
    
    DCL双重检测加锁(进阶懒汉式)
    
    静态内部类实现懒汉式(最推荐写法)
    
    枚举方式(最安全、简洁写法)
    

    参考:java3y & https://www.jianshu.com/p/d35f244f3770

  • 相关阅读:
    找水王
    第十四周学习记录
    第十三周学习记录
    第十二周学习记录
    序列化
    哪个元素出发事件
    阻止默认行为-event.preventDefault();
    阻止时间冒泡 -event.stopPropagation();
    HTML5的LocalStorage和sessionStorage的使用 -缓存
    同步加载、异步加载、延迟加载
  • 原文地址:https://www.cnblogs.com/liuge36/p/12614694.html
Copyright © 2011-2022 走看看