设计模式之单例模式详解

初识单例模式:

定义:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
理解单例模式:
1.单例模式功能:单例模式的功能是用来保证这个类在运行期间只会被创建一个实例,并提供一个全局唯一访问这个类实例的访问点。
2.单例模式的范围:是一个classLoader及其子classLoader的范围;
3.单例模式的命名:一般建议单例模式的方法命名为getInstance();


**单例模式的实现方式(一)**:
//**懒汉模式**
public class Singleton{
	//4.定义一个变量用来存储创建好的实例
	//5.因为这个变量要在静态方法中使用,所以需要加上static来进行修饰
	private static Singleton instance=null;
	//1.私有化构造方法,好在内部进行控制创建实例的数目
	private Singleton(){};
	//2.定义一个方法来为客户端提供实例
	//3.这个方法要定义成类方法,也就是要加上static关键字
	public static synchronized Singelton getInstance(){
		//6.判断存储实例的变量是否有值
		if(instance==null){
			//6.1如果没有值,就创建一个实例,并把这个赋值给存储类型的变量
			instance = new Singleton();
		}
		//6.2如果有值就直接使用
		return instance;
    }
}
//饿汉模式
public class Singleton{
 	//4.定义一个变量用来存储创建好的类实例,直接在这里创建类实例,
 	//直接在这里创建实例,由虚拟机保证只会创建一次。
 	private static Singleton instance=new Singleton();
  	//1.私有化构造方法,控制创建实例的数目
  	private Singleton(){};
  	//2.定义一个方法用来为客户端提供类实例
  	//3.这个方法要定义成类方法,也就是要加上static
  	public static Singelton getInstance(){
  		//5.直接使用已经创建好的实例
		return instance;
	}
}

单例模式的实现方式(二)

  • 双重检测加锁(懒汉模式):双重检测加锁指的是并不是每次进入getInstance()方法都需要加锁,而是先不加锁,进入方法之后,先检查实例是否存在,如果不存在才进入同步块中,这是第一重检查。进入代码块后,再次检查实例是都存在,如果不存在,就在同步的情况下创建一个实例。这是第二重检查,这样一来,就只需要同步一次,从而减少了多次同步情况下进行判断所浪费的时间。
  • 双重加锁机制的实现会使用一个关键字volatile,他的意思就是:被volatile修饰的变量值,将不会被本地线程缓存,所有对该变量的读写,都是直接操作共享内存,从而保证多个线程能正确的处理该变量。
public class Singleton{
	//对保存实例的变量添加volatile进行修饰
	private volatile static Singleton instance=null;
	private Singleton(){};
	public  static Singleton getInstance(){
		//先检查实例是否存在,如果不存在才进入下面的同步块中
		if(instance==null){
			synchronized(Singleton.class){
				//再次检查实例是否存在,如果不存在才真正的创建实例
				if(instance==null){
					instance = new Singleton();
				}
			}
		}
		return instance;
	}
}

单例模式的实现方式(三)

  • 内部类的方式(饿汉模式):这个模式综合使用了java中的类级内部类和多线程缺省同步锁的知识,很巧妙的同时实现了延迟加载和线程安全。
public class Singleton{
	//类级的内部类,也就是静态的成员内部类,该内部类的实例和外部类的实例没有绑定关系
	private static class SingletonHolder{
	//静态初始化器,由jvm保障线程安全
	private static Singleton instance=new Singleton();
	}
    //私有化构造方法
    private Singleton(){};
    private static Singleton getInstance(){
	 	return SingletonHolder.instance;
	}

}

单例模式的实现方式(四)
根据枚举类的特性来实现单例模式,这里不做代码实现;
理解单例模式:
在这里插入图片描述
单例模式体现的思想:

  • 延迟加载的思想
    通俗点说就是一开始不要加载资源或者数据,一直等到需要使用这个资源或者数据了,躲不过去了才加载,所以也称为Lazy Load,不是懒惰,是“延迟加载”,这在实际开发中是一种很常见的思想,尽可能的节约资源。
  • 缓存的思想
    单例模式中的懒汉模式还体现了缓存的思想,缓存也是在实际开发中非常常见的功能。
    简单讲就是,如果某些资源或者数据会被频繁的使用,可以把这些数据缓存在内存中,每次操作的时候,先在内存里面找,看有没有这些数据,如果有那么就直接使用,如果没有,那么就获取它,并设置到缓存中,下一次访问的时候就可以直接从内存中获取它。从而节省了大量的时间,当然,缓存是一种典型的空间换时间的方案。
    单例模式的优缺点:
  • 时间和空间:懒汉模式是典型的时间换空间,饿汉模式是典型的空间换时间。
  • 线程安全:不加同步锁的懒汉单例模式是线程不安全的,饿汉模式是线程安全的,因为虚拟机保证了只会装载一次。
    在这里插入图片描述
    **单例模式思维拓展(不在是单例模式,而是三例模式):
//简单演示如何扩展单例模式,控制实例数目为3(线程不安全)
public class OneExtend{
   	//定义一个缺省的key值的前缀
   	private final static String DEFAULT_PREKEY="cache";
   	//缓存实例的容器
   	private static Map<String,Object> map= new HashMap<String,Object>();
   	//用来记录正在使用的是第几个实例
   	private static int num=1;
   	//定义控制实例的最大数目
   	private final static int NUM_MAX=3;
   	private OneExtend(){};
   	private static OneExtend getInstance(){
  		String key=DEFAULT_PREKEY+num;
  		OneExtend oneExtend = map.get(key);
  		if(oneExtend == null){
			oneExtend = new OneExtend();
			map.put(key,oneExtend);
 		}
 		//把当前实例的序号加1
 		num++;
 		if(num > NUM_MAX){
 		 	//如果实例的序号超过了最大数目,那就重复从1开始获取
 		 	num=1;
 		}
 		return oneExtend ;
    } 
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值