【设计模式】单例模式(Singleton)

来源:互联网 发布:ubuntu u盘启动工具 编辑:程序博客网 时间:2024/06/01 07:17

单例模式的实现方式

3.1 一般情况

饿汉式(最简单的单例实现方式)

class Singleton {    private static  Singleton ourInstance  = new  Singleton();    private Singleton() {    }    public static  Singleton newInstance() {        return ourInstance;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

应用场景:

  • 要求直接在应用启动时加载并初始化
  • 单例对象要求初始化速度非常快且占用内存非常小

懒汉式

懒汉式与饿汉式最大的区别是单例的初始化操作的时机

  • 饿汉式:自动进行单例的初始化
  • 懒汉式:有需要的时候才手动调用newInstance()进行单例的初始化操作
class Singleton {    private static  Singleton ourInstance  = nullprivate Singleton() {    }    public static  Singleton newInstance() {    if( ourInstance == null){        ourInstance = new Singleton();        }        return ourInstance;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

应用场景:

  • 单例初始化的操作耗时比较长而应用对于启动速度又有要求
  • 单例的占用内存比较大
  • 单例只是在某个特定场景的情况下才会被使用,即按需延迟加载单例。

3.2 多线程下的单例模式实现

在多线程的情况下:

  • 对于“饿汉式单例模式”:适用,因为JVM只会加载一次单例类;
  • 对于“懒汉式单例模式”:不适用,因为“懒汉式”在创建单例时是线程不安全的,多个线程可能会并发调用 newInstance 方法从而出现重复创建单例对象的问题。

解决方案:双重校验锁

在同步锁的基础上( synchronized (Singleton.class) 外)添加了一层if,这是为了在Instance已经实例化后下次进入不必执行 synchronized (Singleton.class) 获取对象锁,从而提高性能。

class Singleton {    private volatile static  Singleton ourInstance  = nullprivate Singleton() {    }    public static  Singleton newInstance() {if( ourInstance == null){  synchronized (Singleton.class){      if( ourInstance == null){          ourInstance = new Singleton();          }      }  }        return ourInstance;   }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

解决方案3:静态内部类

在JVM进行类加载的时候会保证数据是同步的,我们采用内部类实现:在内部类里面去创建对象实例。 
只要应用中不使用内部类 JVM 就不会去加载这个单例类,也就不会创建单例对象,从而实现“懒汉式”的延迟加载和线程安全。

class Singleton {    //在装载该内部类时才会去创建单例对象    private static class Singleton2{      private static  Singleton ourInstance  = new Singleton();    }    private Singleton() {    }    public static  Singleton newInstance() {        return Singleton2.ourInstance;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

解决方案4:枚举类型

最简洁、易用的单例实现方式,(《Effective Java》推荐)

  1. package org.mlinge.s10;  
  2.   
  3. public class ClassFactory{   
  4.       
  5.     private enum MyEnumSingleton{  
  6.         singletonFactory;  
  7.           
  8.         private MySingleton instance;  
  9.           
  10.         private MyEnumSingleton(){//枚举类的构造方法在类加载是被实例化  
  11.             instance = new MySingleton();  
  12.         }  
  13.    
  14.         public MySingleton getInstance(){  
  15.             return instance;  
  16.         }  
  17.     }   
  18.    
  19.     public static MySingleton getInstance(){  
  20.         return MyEnumSingleton.singletonFactory.getInstance();  
  21.     }  
  22. }  
  23.   
  24. class MySingleton{//需要获实现单例的类,比如数据库连接Connection  
  25.     public MySingleton(){}   
  26. }  
0 0