设计模式之单例模式

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

单例模式的的基本代码比较简单

/**
 * 
 * @author ricardo
 * @Time 下午10:40:11
 * @Function:定义单例模式类
 *
 */
public class Singleton {
	private static Singleton singleton;
	private Singleton() {}
	
	public static Singleton GetInstance() {
		if(singleton == null)
			singleton = new Singleton();
		return singleton;
	}
}

单例模式中,Singleton类封装了它的唯一实例,以此来控制第三方如何以及何时访问它。也就是对唯一实例的受限访问。

单例模式的应用很简单,举个例子来说明,现在实行一夫一妻制,假设我们现在有一个Wife/Husband 类

/**
 * 
 * @author ricardo
 * @Time 下午10:17:02
 * @Function:姑娘
 *
 */
public class Wife {
	public void Show() {
		System.out.println("秀外慧中的姑娘");
	}
	public void Marry() {
		System.out.println("姑娘要嫁人了");
	}
}
/**
 * 
 * @author ricardo
 * @Time 下午10:18:22
 * @Function:男孩纸
 *
 */
public class Husband {
	private Wife myWife = null;
	
	public void ChooseWife() {		
		if(myWife == null)
			myWife = new Wife();
		myWife.Show();
	}
	
	public void GetMarry() {		
		if(myWife == null)
			myWife = new Wife();
		myWife.Marry();
	}
}	
/**
 * 
 * @author ricardo
 * @Time 下午10:20:35
 * @Function:客户端代码
 *
 */
public class First {
	public static void main(String[] args) {
		Husband husband = new Husband();		
		System.out.println("男孩纸喜欢上一个姑娘");
		husband.ChooseWife();
		System.out.println("姑娘被男孩子打动了");
		husband.GetMarry();		
	}
}
运行截图:


但是这样会有个问题,假设男孩纸的妈妈想见见儿媳,于是:

public class Mother {
	Wife daughter = null;
	public void CheckDaughterInLaw() {		
		if(daughter == null)
			daughter = new Wife();
		daughter.Show();
	}
}
这里母亲会实例化一个Wife出来,很明显,这里出来的并不是男孩子心仪的姑娘了,而不实例化,则会出现空指针。so,我们使用单例来实现

/**
 * 
 * @author ricardo
 * @Time 下午10:17:02
 * @Function:姑娘
 *
 */
public class Wife {
	
	private static Wife wife;
	private Wife() {}
	
	public static Wife newInstance() {
		if(wife == null)
			wife = new Wife();
		return wife;
	}		
	public void Show() {
		System.out.println("秀外慧中的姑娘");
	}
	public void Marry() {
		System.out.println("姑娘要嫁人了");
	}
}
/**
 * 
 * @author ricardo
 * @Time 下午10:18:22
 * @Function:男孩纸
 *
 */
public class Husband {
	private Wife myWife = null;
	
	public void ChooseWife() {
		
		myWife = Wife.newInstance();
		
//		if(myWife == null)
//			myWife = new Wife();
		myWife.Show();
	}
	
	public void GetMarry() {
		myWife = Wife.newInstance();
//		if(myWife == null)
//			myWife = new Wife();
		myWife.Marry();
	}
}
public class Mother {
	Wife daughter = null;
	public void CheckDaughterInLaw() {
		daughter = Wife.newInstance();
//		if(daughter == null)
//			daughter = new Wife();
		daughter.Show();
	}
}
客户端:

/**
 * 
 * @author ricardo
 * @Time 下午10:20:35
 * @Function:客户端代码
 *
 */
public class First {
	public static void main(String[] args) {
		Husband husband = new Husband();
		
		System.out.println("男孩纸喜欢上一个姑娘");
		husband.ChooseWife();
		System.out.println("姑娘被男孩子打动了");
		husband.GetMarry();
		System.out.println("母亲想见见儿媳");
		Mother mother = new Mother();
		mother.CheckDaughterInLaw();
	}
}
这样子,就会看到,姑娘只有唯一一个了。

不过如果将程序扩展一下,假设婚礼准备安排现场直播,这时候就是多线程上场的时候了,但是这样的单例模式没有办法保证在不同线程进入Wife类的时候,进入myWife==null的判定,所以我们需要对Wife进行加锁。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 
 * @author ricardo
 * @Time 下午10:17:02
 * @Function:姑娘
 *
 */
public class Wife {	
	static Lock lock = new ReentrantLock();
	private static Wife wife;
	private Wife() {}
	
	public static Wife newInstance() {
		//如果不加这个判定,每次进入都会被锁上,将严重影响系统性能		
		if(wife == null) {
			lock.lock();
			//如果不加这个判定
			if(wife == null)
				wife = new Wife();
			lock.unlock();
		}
		return wife;
	}		
	public void Show() {
		System.out.println("秀外慧中的姑娘");
	}
	public void Marry() {
		System.out.println("姑娘要嫁人了");
	}
}

我们使用双重判断来优化系统,但是,如果仅仅相对于单例模式来说,可以利用JVM第一次加载类的时候会初始化所有静态变量,所以可以这么来
/**
 * 
 * @author ricardo
 * @Time 下午10:17:02
 * @Function:姑娘
 *
 */
public class Wife {
	
	static Lock lock = new ReentrantLock();
	private static Wife wife = new Wife();;
	private Wife() {}
	
	public static Wife newInstance() {		
//		if(wife == null) {
//			lock.lock();
//			if(wife == null)
//				wife = new Wife();
//			lock.unlock();
//		}
		return wife;
	}		
	public void Show() {
		System.out.println("秀外慧中的姑娘");
	}
	public void Marry() {
		System.out.println("姑娘要嫁人了");
	}
}
理解这样的单例模式,我们也可以通过计数的方式,实现双例模式,三例模式等需要实例化有限次的类。

以上内容,整理自刘径舟,张玉华编著的《设计模式其实很简单》读书笔记,欢迎转载.





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值