设计模式---单例模式

应用场景:程序or系统运行期间中,某个类被要求仅能产生唯一的一个对象,以供使用。

  1. 单例模式的定义:保证一个类仅会产生一个对象,且对外提供一个可被访问的方法。
  2. 一个类能够被创建多个对象的根源,在于类的构造方法是公开的,外部可以通过构造方法去创建多个对象。
  3. 想要控制一个类只能创建一个对象,首先要把外部能创建对象的权限收回,让类自身完成对象的创建工作。其次让类提供一个对外公开的方法间接的去访问对象。这就是单例模式的实现方式。
  4. 单例模式分为懒汉式和饿汉式,区别在类创建对象时实现方式不同。

懒汉式


 // 单例示例   懒汉式
public class Singleton {

  // 定义一个变量来存储创建好的对象 ,此变量要在静态方法中使用,所以需要加上static修饰
  private static Singleton uniqueInstance = null;
    
    // 私有化构造方法,禁止外部创建对象,且好在内部控制创建实例的数目
  private Singleton(){ 
    
  }
    
/**
* 该方法为外部提供唯一的一个对象,该方法需要定义成类方法,由类本身创建去 
* 对象,如果不加static,此方法就变成实例方法,必须先有对象才能调用,而该方法 
* 就是来获得对象的,这样以来变成死循环。有static,就可以直接通过类调用方法 
* 获得对象
 */
  public static synchronized Singleton getInstance(){
        
    if(uniqueInstance == null){
      uniqueInstance = new Singleton();
    }
        
    return uniqueInstance; 
  }
  // 示意方法,单例可以有自己的操作
  public void singletonOperation(){
  }
    
  // 示意属性,单例可以有自己的属性
  private String singletonData;

  // 示意方法,让外部通过这些方法来访问属性的值
  public String getSingletonData(){
    return singletonData;
  }

}

懒汉式:比较懒,只有在第一次使用时才进行对象的创建。因此装载对象的时候不创建对象,private static Singleton uniqueInstance = null;


饿汉式

// 饿汉式单例实现的示例
public class Singleton {
    
    // 定义变量来存储创建好的类实例,直接在这里创建类实例,static只会创建一次
    private static Singleton uniqueInstance = new Singleton();
    
    // 私有化构造方法,好在内部控制创建实例的数目
    private Singleton(){
        //
    }
    
    // 定义一个方法来为客户端提供类实例
    public static Singleton getInstance(){
        //直接使用已经创建好的实例
        return uniqueInstance;
    }
    
    // 示意方法,单例可以有自己的操作
    public void singletonOperation(){
        //功能处理
    }
    
    // 示意属性,单例可以有自己的属性
    private String singletonData;
    
    // 示意方法,让外部通过这些方法来访问属性的值
    public String getSingletonData(){
        return singletonData;
    }
}

饿汉式:既然饿,那么在创建对象的时候就比较着急,于是在装载类的时候就创建了对象。private static Singleton uniqueInstance = new Singleton(); 使用了static的特性。


调用顺序示意图

懒汉式

饿汉式

衍生思想

  1. 延迟加载的思想:一开始不要加载数据或者资源,等马上要被使用了,才去加载。很节约资源
  2. 缓存思想:把频繁使用到的数据,缓存到内存中,每次操作的时候,先到内存里查找,有直接拿来用,没有就去获取它。下次访问的时候节约大量的时间,是一种空间换时间的方案。
  3. 懒汉式线程不安全,饿汉式线程安全,虚拟机保证只会装载一次,装载类的时候不会出现并发。
  4. 另一种巧妙的实现单例模式
public class Singleton {

    // 定义静态成员内部类,该内部类的实例与外部类的实例 
    // 没有绑定关系, 而且只有被调用到才会装载,从而实现了延迟加载
    
    private static class SingletonHolder{

        // 静态初始化器,由JVM来保证线程安全
         private static Singleton instance = new Singleton();
    }
    
    // 私有化构造方法
    private Singleton(){
    }
    
    public static  Singleton getInstance(){
        return SingletonHolder.instance;
    }
}
  1. 使用枚举实现单例模式
/**
* 使用枚举来实现单例模式的示例
*/
public enum Singleton { 
   /**
    * 定义一个枚举的元素,它就代表了Singleton的一个实例
    */
   uniqueInstance;
   
   /**
    * 示意方法,单例可以有自己的操作
    */
   public void singletonOperation(){
       //功能处理
       System.out.println("aa=="+Singleton.uniqueInstance.hashCode());
   }
}
public class Client {
    public static void main(String[] args) {
        for(int i=0;i<3;i++){
            Singleton.uniqueInstance.singletonOperation();
        }
    }
}
  • 单例模式的本质:控制对象的个数。
  • 何时选择单例模式:需要控制住类的实例只有一个,且外部只能从一个访问点访问实例,此时需要用到单例模式。

留一个小思索:
现在需要一个类产生3个固定的对象,而不是1个。此时该怎么办呢?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。