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)
  • 相关阅读:
    Asp.net弹出浏览器客户端确认对话框代码 Carlwave
    VS 2005 与SQL Server 2005整合优势在哪里?(from csdn.net) Carlwave
    如何让搜索引擎收录我的站点 Carlwave
    超强扩展性的DNNDotNetNuke模块功能分类列表(from 中国DNN) Carlwave
    DotNetNuke命名空间概述 Carlwave
    Most Popular Questions and Answers on ASP.NET Whidbey(from asp.net forums,write by ASP.NET Team) Carlwave
    火箭官方宣告麦蒂缺阵五周 季后赛前景蒙上阴影 Carlwave
    asp.net有效使用缓存(转) Carlwave
    《Business Rules Engine Overview》《业务规则引擎概述》write by Mark Kamoski Carlwave
    中国详细省市县自治区名称列表(含access数据库和sql2000备份数据库) Carlwave
  • 原文地址:https://www.cnblogs.com/linkworld/p/7439672.html
Copyright © 2011-2022 走看看