设计模式(一) 单例模式

核心作用:

  保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

常见应用场景:

 

 

单例模式的优点:

  1. 由于单例模式只生成一个实例,减少了系统的开销,当一个对象的产生需要比较多的资源师,如:读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式来解决
  2. 单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类负责所有数据表的映射处理

 常见的五种单例模式实现方式:

 

  • 饿汉式(线程安全,调用效率高,不能延时加载)

    解释:饿汉式单例代码中,static变量会在类装载是初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟保证只会装载一次该类,肯定不会发生并发访问的问题。因此不需要synchronized关键字

    问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费

  

package com.lp.singleton;
/*测试饿汉式单例模式*/
/*当类实例化的*/
public class SingletonDemo1 {
    //    ctrl + m 快捷键  优化界面 
    //    重点:类初始化时立即加载
    private static SingletonDemo1 instance = new SingletonDemo1();
    //这个函数规定了外部不能实例化这个类的对象
    private SingletonDemo1(){
        
    }
    //方法没有同步,调用效率高
    public static SingletonDemo1 getInstance(){
        return instance;
    }
        
}

 

  • 懒汉式(线程安全,调用效率不高,可以延时加载)

    问题:资源利用率高了,但是,每次调用getInstance方法都要同步,并发效率低

 

package com.lp.singleton;

/*测试懒汉式单例模式*/
public class SingletonDemo2 {
    //    ctrl + m 快捷键  优化界面 
    //    重点:类初始化时不加载
    private static SingletonDemo2 s;
    //这个函数规定了外部不能实例化这个类的对象
    private SingletonDemo2(){
        
    }
    //方法同步,调用效率低
    public static synchronized SingletonDemo2 getInstance(){
        if(s == null){
            s = new SingletonDemo2();
        }
        return s;
    }
        
}

 

  • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)

 

package com.lp.singleton;
/*这个模式不建议用*/
public class SingletonDemo3 {
    private static SingletonDemo3 instance = null;
    public static SingletonDemo3 getInstance(){
        if(instance == null){
            SingletonDemo3 sc ;
            synchronized(SingletonDemo3.class){
                sc = instance;
                if(sc == null){
                    synchronized(SingletonDemo3.class){
                        if(sc == null){
                            sc = new SingletonDemo3();
                        }
                    }
                    instance = sc;
                }
            }        
        }
        return instance;
    }
    
    private SingletonDemo3(){
        
    }
}

 

  • 静态内部类式(线程安全,调用效率高 , 可以延时加载)

    要点:1:外部类没有static属性,则不会像饿汉式那样立即加载对象

       2:只有真正调用getInstance() ,才会加载静态内部类,加载类时线程是安全的,instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全性.

       3:兼备了并发高效调用和延迟加载的优势!

      

package com.lp.singleton;
//集合了线程安全 高效调用  延时加载 三个有点
public class SingletonDemo4 {
    private static class SingletonClassInstance{
        private static final SingletonDemo4 instance = new SingletonDemo4();
    }
    
    private SingletonDemo4(){
        
    }
    
    public static SingletonDemo4 getInstance(){
        return SingletonClassInstance.instance;
    }
}

 

  • 枚举单例(线程安全,调用效率高,不能延时加载 )

    优点:  1:实现简单

        2:枚举本身就是单例模式,由JVM从根本上提供保障!避免通过反射和反序列化的漏洞

 

package com.lp.singleton;

/*测试枚举式实现单例模式*/
/*唯一缺点:没有延时加载的效果*/
/*防止反射和发序列化漏洞*/
public enum SingletonDemo5 {
    
    //这个枚举元素,本身就是单例对象!
    INSTANCE;    
    
    //添加自己需要的操作
    public void singletionOperation(){
        
    }
}

 


 

如何选用:

--单例对象  占用资源 少,不需要 延时加载:

  • 枚举式  好于 饿汉式

--单例对象  占用资源 大,需要 延时加载:

  • 静态内部类  好于 懒汉式

  

 

posted @ 2015-04-11 18:29  李_鹏  阅读(174)  评论(0编辑  收藏  举报