美文网首页设计模式
设计模式——单例模式

设计模式——单例模式

作者: 程序员will | 来源:发表于2019-06-18 10:50 被阅读0次

    什么是设计模式

    设计模式简单来说就是工程师们经过长期编程,总结的一套固定的编程模式,就像盖房子,本来是随便盖的,但是经过长期实践,建筑者们形成了一套建筑的固定套路,比如哥特式建筑怎么建,四合院怎么建等等。
    对应到程序员的软件工程行业,我们其实也是在建造“屋子”,这套设计模式就是我们编程的基本思路。
    设计模式有很多种,这里介绍其中最简单也最常用的单例模式。

    单例模式即,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。

    单例模式实现

    懒汉模式(单线程,类加载时不初始化,线程不安全)

    public class LazySingleton  {
    
        private static LazySingleton  instance = null;
    
        private LazySingleton () {
        }
    
        public static LazySingleton  getInstance() {
            if (instance == null) {
                instance = new LazySingleton ();
            }
            return instance;
        }
    }
    

    由于单例模式下,该对象只能生成一次,所以重构该类的默认构造方法为Private,但是这样又导致其他类无法访问,所以定义一个public的获取对象的方法getInstance(),该方法表明,当对象不存在时new一个类对象,否则返回对象,这样就实现了只能创建一个实例。
    在其他类中,调用这个方法获取该类的实例。


    测试类:

    public class TestSingletom {
        
        public static void main(String[] args) {
            LazySingleton  s1 = LazySingleton .getInstance();
            LazySingleton  s2 = LazySingleton .getInstance();
            if(s1==s2){
                System.out.println("创造的是相同的对象");
            }else{
                System.out.println("创造的是不同的对象");
            }
        }
    }
    //返回结果为:
    创造的是相同的对象
    

    懒汉模式进阶版本(单线程,单线程,类加载时不初始化)

    public class LazySingleton  {
    
        private static LazySingleton  instance = null;
    
        private LazySingleton () {
        }
    
        public static synchronized LazySingleton  getInstance() {
            if (instance == null) {
                instance = new LazySingleton ();
            }
            return instance;
        }
    }
    

    这里和前一个模式的唯一区别在于新加了一个synchronized,这是因为在多线程的情况下,如果两个线程同时运行到判断instance是否为null的if语句时,并且instance的确没有创建时,那么两个线程都会创建一个实例,此时Singleton就不能满足单例模式的要求了。
    为了保证在多线程环境下我们还只能得到类的一个实例,需要加上一个同步锁。


    饿汉模式(在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快)

    public class EagerSingleton {
        //饿汉单例模式
        //在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快
    private static EagerSingleton instance = new EagerSingleton();
    //静态私有成员,已初始化
    
    private EagerSingleton() 
    {
        //私有构造函数
    }
    
    public static EagerSingleton getInstance()    
    //静态,不用同步(类加载时已初始化,不会有多线程的问题)
    {
        return instance;
    }
    }
    

    这种方法不会有线程问题,但是缺点是它不是一种懒加载模式式(lazyinitialization),单例会在加载类后一开始就被初始化,即使客户端没有调用 getInstance()方法。


    最优办法:静态内部类 实现单例模式

    public class Singleton5 {
    
        private static class SingletonHolder {
            private static final Singleton5 INSTANCE = new Singleton5();
        }
    
        private Singleton5() {
        }
        public static final Singleton5 getInstance() {
            return SingletonHolder.INSTANCE;
        }
    }
    

    由于 SingletonHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;


    另外:
    有人提问,例模式跟全局变量有什么区别?

    他们的区别在于:全局变量是一个变量,存在于某个具体的类中,而单例是一个对象,可以存在于整个应用。

    相关文章

      网友评论

        本文标题:设计模式——单例模式

        本文链接:https://www.haomeiwen.com/subject/pmvxqctx.html