Spring 模式系列(四)- Singleton Pattern (单例模式)

在我的程序生涯中使用单例模式用的次数和工厂模式差不多,但在Spring中,使用的次数会更多。因为,在Spring里面,一切皆是单例。当你在Spring中创建一个Bean时,默认就是一个单例,除非你跟我们的老朋友Application Context特别要求,不然你就得到一个单例的Bean。那么有些朋友会问我,什么是特别要求,我在接下来的系列中提到Prototype模式时,会提到这个特别要求。值得一提的是,接下来我会介绍传统的单例模式,这个跟Spring的实现有所不同,但是原理是一样的。

[WHY]首先我们说说为什么要有这样的模式,它能解决什么问题?

我总结下来有以下三点

  1. Expensive object creation
  2. Control concurrency associated shared resources
  3. Storing static state for multiple parts of the application

首先谈谈第一点 – Expensive object creation,在实际工作中,大家往往要构建一些占用大量的i/o 或memory的object,比如我们熟悉的database connection object,remote call的那些client object (用过Apache CXF的同学应该比较熟悉)。这些object建造起来往往花费大量时间,但是又易于重复使用。因此,聪明的同学们应该猜到,只要结合单例模式和建一个线程池(pool)就能解决这个问题。相信大家应该有点感觉,这个就是传统的jdbc pool的解决方案。

第二点原因则是共享的问题,Web Application是一个高并发的例子,比如所有requests共享的web context,上面提到的database connection也是一个共享资源。那么原理很简单,要共享,那就只有一个 – 也就是单例

第三点则是你需要控制Application全局的状态。比如,当前比较流行的single page application,一个页面有n个components,那么如果这些components拥有一些共享的状态,比如,这些component有一个user的属性,当你log in后,所有components都share这个state,除非你用另外一个user,那么所有components 的state都会变,很明显,这个state就是一个单例。

[HOW]那么下面我来谈谈如何实现?

我们可爱的bean,因为它们是单例,因为它们必须是thread safe的。因而,这个模式非常容易理解,首先你有一个class,这个class存储着一个reference指向自己,或者说,一个自己的instance。然后,你需要有一个private constructor,然后你有一个static getinstance method 去返回自己, 把constructor私有化使得你在getInstance method用不了new method去构建新的instance。由于多线程同时共享同一个instance,那么你在调用时必须引入一些locking的logic,比如synchronized block去保证unsafe的情况。

接下来的代码来自于我工作中的一段代码,这段代码的作用是构建出一个调用SOAP Webservice的service client,当中利用一个object pool和单例模式。

public class OrderWSClientFacade {

	private static volatile Service orderService = null;
	private static ObjectPool<OrderWSPortHolder> orderServicePortPool;

	public OrderWSClientFacade(String serviceLocation) throws MalformedURLException     {
	//check before multiple threads acquire lock
	if(orderService == null){
		synchronized(this) {
			//check before actual port initialization once, one of the thread gets access to this block
			if(orderService == null){
				try
				{
					URL url = new URL(serviceLocation);
					orderService = new OrderCWS(url);
					GenericObjectPoolConfig orderServicePortPoolConfig = new GenericObjectPoolConfig();
					orderServicePortPool = new GenericObjectPool<OrderWSPortHolder>( new OrderServicePortFactory(),orderServicePortPoolConfig);  // initialize the Pool ONLY once !!

					// ignore some lines of code of configuration

				}	
				catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值