zoukankan      html  css  js  c++  java
  • 计模式之单件模式(单例模式)

    单件模式是最简单的设计模式啦!(窝感觉~~)

    有一些对象我们只需要一个,例如:线程池(threadpool),缓存(cache),充当打印机,显卡等设备的驱动程序的对象。

    这些类对象只能有一个实例,多了会出现一些问题。

    全局变量缺点:必须在一开始就创建对象,浪费资源。

    只创建一个对象的方法:首先将构造函数私有,这样这个类就不会随意的创建了。然后为类创建一个产生实例变量的方法。

    public class MyClass {
        private MyClass() {}
        public static MyClass getIntance() {
            return new MyClass();
        }
    }    

    单件模式的实现:

    public class Singleton {
        
        private static Singleton uniqueSingleton; 
        
        private Singleton() { }
        
        public static Singleton getInstance() {
            if (uniqueSingleton == null) {
                uniqueSingleton = new Singleton();
            }
            return uniqueSingleton;
        }
        
        
    }

    如果不需要这个实例,它就永远不会被产生,这就是“延迟实例化”(lazy-instantiaze)

    单件模式:确保一个类只有一个实例,并提供一个全局访问点。

    但是在多线程情况下,会产生一些问题,如下图情况:

    呀~~产生了两个对象!

    于是在多线程的时候

    需要把getInstance()函数变成同步方法啦

    public static synchronized Singleton getInstance() {
        if (uniqueSingleton == null) {
            uniqueSingleton = new Singleton();
        }
        return uniqueSingleton;
    }

    但是……同步会降低性能……

    1.如果getInstance()方法的性能对应用程序不是很关键,就这样就可以了。

    2.如果程序总是创建并使用单件实例,或者在创建或运行时方面的负担不太繁重,可以一开始就创建实例。

    public class Singleton {
        
        private static Singleton uniqueSingleton = new Singleton(); 
        
        private Singleton() { }
        
        public static Singleton getInstance() {
            return uniqueSingleton;
        }
        
    }

    3.用双重加锁,在getInstance()中减少使用同步

    public class Singleton {
        
        private volatile static Singleton uniqueSingleton;    // volatile关键字确保  当uniqueSingleton被初始化后
                                                              // 多个线程正确的处理uniqueSingleton变量
        
        private Singleton() { }
        
        public static Singleton getInstance() {
            if (uniqueSingleton == null) {                    // 检查实例  如果不存在就进入同步区
                synchronized (Singleton.class) {
                    if (uniqueSingleton == null) {            // 进入区块后  在检查一次  如果仍然是null 才创建实例
                        uniqueSingleton = new Singleton();    // 注意:只有第一次才彻底执行这里的代码
                    }
                }
            }
            return uniqueSingleton;
        }
        
    }

    4. 通过枚举实现单例模式

    通过内部静态enum的方法来实现,因为JVM会保证enum不能被反射并且构造器方法只执行一次。

    public class EnumSingleton {
        private EnumSingleton() {}
        
        public static EnumSingleton getInstance(){
            return Singleton.INSTANCE.getInstance();
        }
        
        private static enum Singleton{
            INSTANCE;
            
            private EnumSingleton singleton;
            //JVM会保证此方法绝对只调用一次
            private Singleton(){
                singleton = new EnumSingleton();
            }
            public EnumSingleton getInstance() {
                return singleton;
            }
        }
    }
  • 相关阅读:
    LeetCode 252. Meeting Rooms
    LeetCode 161. One Edit Distance
    LeetCode 156. Binary Tree Upside Down
    LeetCode 173. Binary Search Tree Iterator
    LeetCode 285. Inorder Successor in BST
    LeetCode 305. Number of Islands II
    LeetCode 272. Closest Binary Search Tree Value II
    LeetCode 270. Closest Binary Search Tree Value
    LeetCode 329. Longest Increasing Path in a Matrix
    LintCode Subtree
  • 原文地址:https://www.cnblogs.com/wenruo/p/6533648.html
Copyright © 2011-2022 走看看