zoukankan      html  css  js  c++  java
  • Java 之单例设计模式

    设计模式: 对问题行之有效的解决方式, 其实它是一种思想.

    单例设计模式

    解决的问题:就是可以保证一个类在内存中的对象唯一性. 即单个实例.

    比如对于A 和 B 两个程序使用同一个配置信息对象时, A 对配置信息作出修改, B 也与之对应的更新配置信息, 即需要保证该对象的唯一性.

    如何保证对象唯一性呢?
    1. 不允许其他程序用 new 创建该类对象
    2. 在该类中创建一个本类实例
    3. 对外提供一个方法让其他程序可以获取该对象.
    步骤:
    1. 私有化该类构造函数
    2. 通过 new 在本类中创建一个本类对象
    3. 定义一个公有方法, 将创建的对象返回
    两种方式
    1. 饿汉式: 类一加载, 对象就存在了.
    2. 懒汉式: 类加载进来, 没有对象, 只有调用 getInstance 方法时, 才会创建对象.
      也称为 单例设计模式的延迟加载模式. 但是, 懒汉式在多线程访问时,存在安全隐患.
    // 第一种方式: 饿汉式
    class Single
    {
        Single s = new Single(); // 在本类中创建一个本类对象
    
        private Single(){} // 私有化该类构造函数
    
        // 定义一个公有方法, 将创建的对象返回. 用于返回对象 s, 所以返回类型 Single
        public Single getInstance()
        {
            return s;
        }
    }
    
    class SingleDemo
    {
        public static void main(String[] args)
        {
            Single ss = Single.getInstance();
        }
    }
    
    /*
    分析一: main 函数中, getInstance 方法调用不能使用对象调用, 只能使用类名调用.
           所以 Single 类中该方法需要使用 static 修饰.
    分析二: getInstance 方法为静态方法, 它访问的内容必须是静态的,所以对象 s 也需要静态修饰.
    */
    // 改进
    class Single
    {
        private static Single s = new Single();
    
        private Single(){}
    
        public static Single getInstance() // 提供该方法访问实例对象 s, 是为了对象的可控
        {
            return s;
        }
    }
    
    class SingleDemo
    {
        public static void main(String[] args)
        {
            Single ss = Single.getInstance();
        }
    }
    
    // 第二种方式: 懒汉式
    // 类加载进来, 没有对象, 只有调用 getInstance 方法时, 才会创建对象.
    class Single2
    {
        private static Single2 s = null;
    
        private Single(){}
    
        public static Single2 getInstance()
        {
            if(s==null)
                s = new Single2();
            return s;
    }
    }
    // 示例:下列代码的输出结果
    class SingleDemo
    {
        public static void main(String[] args)
        {
            Test t1 = Test.getInstance();
            Test t2 = Test.getInstance();
            t1.setNum(10);
            t2.setNum(20);
            System.out.println(t1.getNum()); // 输出 20
            System.out.println(t2.getNum()); // 输出 20
    }
    }
    
    class Test
    {
        private int num;
    
        private static Test t = new Test();
        private Test(){}
        public static Test getInstance()
        {
            return t;
        }
    
        public void setNum(int num)
        {
            this.num = num;
        }
    
        public int getNum()
        {
            return num;
        }
    }
    
    // 懒汉式二:避免多线程同时调用getInstance()方法, 可以使用关键字synchronized
    class LazySingleton {
        private static LazySingleton instance = null;
    
        private LazySingleton(){}
    
        public synchronized static LazySingleton getInstance() {
            if(instance == null){
                instance = new LazySingleton();
            }
            return instance;
        }
    }
    
    // 懒汉式三:为提高系统性能,对"instance = new LazySingleton()"进行锁定
    class LazySingleton{
        private static LazySingleton instance = null;
    
        private LazySingleton(){}
    
        public static LazySingleton getInstance(){
            if(instance == null){                   // 此处,有可能造成单例对象不唯一
                synchronized(LazySingleton.class){
                    instance = new LazySingleton();
                }
            }
            return instance;
        }
    }
    
    // 懒汉式四:双重检查锁定(Double-Check Locking)
    class LazySingleton{
        // 注意,此处增加修饰符 volatile
        private volatile static LazySingleton instance = null;
    
        private LazySingleton(){}
    
        public static LazySingleton getInstance(){
            // 第一重判断
            if(instance == null){
                // 锁定代码块
                synchronized(LazySingleton.class){
                    // 第二重判断
                    if(instance == null){
                        instance = new LazySingleton();
                    }
                }
            }
            return instance;
        }
    }
    
    //单例第三种方式: Initialization Demand Holder(IoDH)技术
    // 在单例类中增加一个静态(static)内部类
    class Singleton{
        private Singleton(){}
    
        // 静态类
        private static class HolderClass {
            private final static Singleton instance = new Singleton();
        }
    
        public static Singleton getInstance() {
            return HolderClass.instance;
        }
    
        public static void main(String args[]){
            Singleton s1, s2;
            s1 = Singleton.getInstance();
            s2 = Singleton.getInstance();
            System.out.println(s1 == s2);
        }
    }
    



    _参考资料_ - [JavaSE 基础视频(毕向东)](https://www.bilibili.com/video/av3092292/#page=4) - [单例模式中的双重检查](http://blog.csdn.net/chenchaofuck1/article/details/51702129)
  • 相关阅读:
    gorilla/mux 的学习
    SwitchyOmega 配置
    golang []byte 和 string相互转换
    golang 并发demo 写入 redis
    VS2010 显示TFS删除项
    WPF之转换器
    DataTemplate的用法
    DynamicResource与StaticResource的区别
    除非Windows Activation Service (WAS)和万维网发布服务(W3SVC)均处于运行状态,否则无法启动网站。
    WPF 可视化树的用途
  • 原文地址:https://www.cnblogs.com/linkworld/p/7439672.html
Copyright © 2011-2022 走看看