zoukankan      html  css  js  c++  java
  • 设计模式-单例模式

    1、单例模式的定义

         保证一个类仅有一个实例,并提供一个访问它的全局实例。本质就是控制对象实例的个数

    2、单例模式分为两种:

       懒汉式,在对象创建实例的时候,等到要使用对象的实例的时候才创建。属于线程不安全的。代码如下所示:

    package org.struct;
    
    public class Singleton {
    	private static Singleton instance = null;
    
    	public synchronized static Singleton getInstance() {
    		if (instance == null) {
    			instance = new Singleton();
    		}
    		return instance;
    	}
    }
    

      调用方式如下所示:

          

       饿汉式,就是java jvm在装载类的时候就直接创建了实例,是属于线程安全。懒汉式代码如下:

    package org.struct;
    
    public class Singleton {
    	private static Singleton instance = new Singleton();
    
    	public static Singleton getInstance() {
    		return instance;
    	}
    }
    

      客户端调用顺序图如下所示:

         

          单例模式中懒汉加载的实现方式体现了延迟加载的思想,那么什么是延迟加载呢?就是在没有使用的时候不加载数据,一直等,等到马上要使用这个资源或者数据了,必须要加载才去加载数据,成为Lazy Load,体现延迟加载的代码如下,在要使用实例的时候才去判断,要是还没有创建实例,则马上创建。当绕,缓存也是一种典型的用空间换取时间的方案

    if (instance == null) {
    	instance = new Singleton();
    }
    

    3、java中缓存的基本实现方式。在java代码中,可以使用map实现缓存,思路如下:
         (1)、先到缓存中查找,看看是否存在需要的资源

         (2)、如果没有找到,那么就创建一个满足要求的数据,然后把这个数据设置到缓存中,以备下次使用。

      下面是一个实现比较简单的示例代码:

    package org.struct;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class JavaCache {
    	private Map<String, Object> map = new HashMap<String, Object>();
    
    	public Object getValue(String key) {
    		Object obj = map.get(key);
    		if (obj == null) {
    			obj = key + ",value";
    			map.put(key, obj);
    		}
    		return obj;
    	}
    }
    

    单例模式更好的实现方式

    package org.struct;
    
    public class Singleton {
    	private static class SingletonHolder {
    		private static Singleton instance = new Singleton();
    	}
    	public static Singleton getInstance() {
    		return SingletonHolder().instance;
    	}
    }
    

    当getInstance第一次被调用的时候,它第一次读取SingletonHolder().instance;导致SingletonHolder类初始化,会初始化它的静态域,从而创建Singleton,由于此为静态域,因此在虚拟机装载类的时候就已经初始化,线程安全又java虚拟机维护

    最后一个问题,既然单例模式是控制实例的个数,前面讨论的都是只有一个实例,那么是否可以自己控制实例的数量呢?答案是肯定的,也是使用Map实现,本处只考虑控制实例的个数吗,其他的没有考虑。示例代码如下:

    package org.struct;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class MultInstance {
    	private final static String DEFAULT_KEY = "carche";
    	private static Map<String, MultInstance> map = new HashMap<String, MultInstance>();
    	private static int num = 1;
    	private final static int num_max = 3;
    
    	public static MultInstance getInstane() {
    		String key = DEFAULT_KEY + num;
    		MultInstance m_insInstance = map.get(key);
    		if (m_insInstance == null) {
    			m_insInstance = new MultInstance();
    			map.put(key, m_insInstance);
    		}
    		num++;
    		if (num > num_max) {
    			num = 1;
    		}
    		return m_insInstance;
    	}
    
    	public static void main(String[] args) {
    		System.out.println("-->"+getInstane());
    		System.out.println("-->"+getInstane());
    		System.out.println("-->"+getInstane());
    		System.out.println("-->"+getInstane());
    		System.out.println("-->" + getInstane());
    	}
    }

    运行结果如下所示:

    -->org.struct.MultInstance@146ccf3e
    -->org.struct.MultInstance@7399f9eb
    -->org.struct.MultInstance@1e6ee98
    -->org.struct.MultInstance@146ccf3e
    -->org.struct.MultInstance@7399f9eb

    通过上面的运行结果看,美中不足的有:1、线程仍然是不安全的。2、生成的实例的顺序是不能保证的。

    4、使用场景

    当需要控制一个类的实例个数只有一个的时候,而且用户只能从一个全局变量访问它的时候,就可以考虑单例模式了。

    
    

      

  • 相关阅读:
    远程接入系统的问题
    FastReport
    通用FASTREPORT打印模块及接口方法
    cxGrid控件过滤筛选后如何获更新筛选后的数据集
    Oracle Data Integrator 12c (12.1.2)新特性
    ODI 12c 安装
    Kafka面试题
    Hadoop面试题
    Spark面试题
    JAVA面试题-数组字符串基础
  • 原文地址:https://www.cnblogs.com/gyouxu/p/4004125.html
Copyright © 2011-2022 走看看