研磨设计模式学习笔记之单例模式

1、单例模式定义:保证一个类仅有一个实例,并提供一个访问它的全局访问点 。   

2、单例模式结构及说明:Singleton:负责创建Singleton类自己的唯一实例,并提供一个getInstance的方法,让外部来访问这个类的唯一实例。 

3、单例模式示例代码:

  3.1 单例模式又分为饿汉式与懒汉式单例模式。

        饿与懒的区别,饿表示的是在程序加载的时候即创建一个静态实例。懒顾名思义即当在需要他的时候才会创建。

  3.2 恶汉式代码:

     

package singleton;

/**
 * 懒汉式单例模式
 * @author Administrator
 *
 */
public class SingletonSample2 {
	/**
	 * 定义一个变量来存储创建好的类的实例
	 */
	private static SingletonSample2 uniqueInstance= null;
	
	/**
	 * 私有构造方法,可以在内部控制创建实例的数目
	 */
	private SingletonSample2(){
	}

	/**
	 * 定义一个方法来为客户端提供实例
	 * @return
	 */
	public static synchronized SingletonSample2 getInstance(){
		//判断存储实例的变量是否有值
		if(null == uniqueInstance){
			//如果没有,就创建一个类实例,并把值赋给存储类实例的变量
			uniqueInstance = new SingletonSample2();
		}
		//有值就直接返回
		return uniqueInstance;
	}
	
	/**
	 * 定义自己的方法
	 */
	public void singletonOperation(){
		
	}
	
	/**
	 * 定义自己的属性
	 */
	private String singletonData;

	public String getSingletonData() {
		return singletonData;
	}
	public void setSingletonData(String singletonData) {
		this.singletonData = singletonData;
	}
	
}
测试类
public class SingletonTest {
	
	public static void main(String[] args) {
		
		SingletonSample2 s21 = SingletonSample2.getInstance();
		SingletonSample2 s22 = SingletonSample2.getInstance();
		System.out.println(s21==s22);
	}

}
测试结果:返回true


  3.2 懒汉式代码:

package singleton;

/**
 * 恶汉式单例模式
 * @author Administrator
 *
 */
public class SingletonSample1 {
	
	/**
	 * 定义一个变量来存储创建好的类的实例,直接在这里创建类的实例,只能创建一次
	 */
	private  static  SingletonSample1 uniqueInstance= new SingletonSample1();
	
	/**
	 * 私有构造方法,可以在内部控制创建实例的数目
	 */
	private SingletonSample1(){
	}

	/**
	 * 定义一个方法来为客户端提供实例
	 * @return
	 */
	public static SingletonSample1 getInstance(){
		return uniqueInstance;
	}
	

	/**
	 * 定义自己的方法
	 */
	public void singletonOperation(){
		
	}
	
	/**
	 * 定义自己的属性
	 */
	private String singletonData;

	public String getSingletonData() {
		return singletonData;
	}
	public void setSingletonData(String singletonData) {
		this.singletonData = singletonData;
	}
}

4、单例模式线程安全性: 不加同步的懒汉式是线程不安全的,在多线程的环境中可能会导致并发问题。而饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候不会发生并发的。

  4.1 如何实现懒汉式线程安全呢? 当然可以直接在getInstance()方法上加上synchronized关键字。但这样就会降低整个访问的速度,而且每次都要判断。故出现了双重检查加锁。

  4.2 双重检查加锁机制:指的是并不是每次进入getInstance方法都需要同步,而是先不同步,进入方法过后,先检查实例是否存在,如果不存在才进入下面的同步块,这是第一重检查。进入同步块过后,再次检查实例是否存在如果不存在,就在同步块的情况下创建一个实例,这就是第二重检查。这样一来,就只需要同步一次了。从而减少了多次在同步的情况下进行的判断而浪费的时间。 不多说,上代码。

package singleton;

/**
 * 双重检查加锁懒汉式单例模式
 * @author Administrator
 *
 */
public class SingletonSample3 {
	/**
	 * 定义一个变量来存储创建好的类的实例需添加volatile修饰
	 */
	private volatile static SingletonSample3 uniqueInstance= null;
	
	/**
	 * 私有构造方法,可以在内部控制创建实例的数目
	 */
	private SingletonSample3(){
	}

	/**
	 * 定义一个方法来为客户端提供实例
	 * @return
	 */
	public static SingletonSample3 getInstance(){
		//判断存储实例的变量是否有值
		if(null == uniqueInstance){
			//同步块,线程安全地创建实例
			synchronized (SingletonSample3.class) {
				//再次检查实例是否存在,如果不存在才真正的创建实例
				if(null == uniqueInstance){
					uniqueInstance = new SingletonSample3();
				}
			}
		}
		//有值就直接返回
		return uniqueInstance;
	}
	
	/**
	 * 定义自己的方法
	 */
	public void singletonOperation(){
		
	}
	
	/**
	 * 定义自己的属性
	 */
	private String singletonData;

	public String getSingletonData() {
		return singletonData;
	}
	public void setSingletonData(String singletonData) {
		this.singletonData = singletonData;
	}
	
}
(建议双重检查加锁用在java5及以上版本。)

5、单例模式的更好实现方式:类级内部类。

  5.1 类级内部类:有static修饰的成员式内部类。如果没有static修饰的成员内部类被称为对象内部类。

  5.2 多线程缺省同步锁。

         在多线程开发中,为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制。但是某些情况中,虚拟机已经隐含地为您执行了同步,这些情况就不用直接再来进行同步控制了。这些情况包括:

  • 由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时
  • 访问final字段时
  • 在创建线程之间创建对象
  • 线程可以看见它要处理的对象时

   5.3 更为简单的实现单例模式实例代码

package singleton;

/**
 * 双重检查加锁懒汉式单例模式
 * @author Administrator
 *
 */
public class SingletonSample4 {
	/**
	 * 类级内部类
	 * 没有绑定关系,而且只有在调用的时候才会加载,从而实现了延迟加载
	 */
	private static class SingletonHolder{
		/**
		 * 静态初始化器,由JVM来保证线程安全
		 */
		private static SingletonSample4 instance = new SingletonSample4();
	}
	
	public static SingletonSample4 getInstance(){
		return SingletonHolder.instance;
	}
	
	/**
	 * 私有构造方法
	 */
	private SingletonSample4(){
	}
	/**
	 * 定义自己的方法
	 */
	public void singletonOperation(){
		
	}
	
	/**
	 * 定义自己的属性
	 */
	private String singletonData;

	public String getSingletonData() {
		return singletonData;
	}
	public void setSingletonData(String singletonData) {
		this.singletonData = singletonData;
	}
	
}
6、还有种更为简洁,高效,安全的实现单例方法--- 通过枚举来显示单例模式。

package singleton;

public enum SingletonSample5 {
	/**
	 * 定义一个枚举元素,它就代表了Singleton的一个实例
	 */
	uniqueInstance;
	
	/**
	 * 自定义方法
	 */
	public void singletonOperation(){
		
	}

}

以上是单例的模式的几种不同的实现方式,与大家一同学习。


Little progress every day!











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值