您的位置:首页 > 编程语言 > Java开发

Java项目(5)——单例模式的应用与研究

2014-10-29 22:24 330 查看
单例模式是很别致的一个模式,很少有人拿它跟其他模式相比,因为,单例模式很简单,很特别,作用就是保证一个类有唯一一个实例,并让一个全局变量使得它能被访问.而保证这个类只被实例化一次的办法就是把构造函数变为私有的,除了它自己都不能new新对象,然后把实例化的过程写在类自身的公有方法里,是否new新对象只有它自己判断决定,已经有了一个实例就直接返回已存在的对象,没有就new一个新实例.其他类想实例化一个对象时调这个公有方法.

饿汉式(预先初始化对象)

//饿汉式
Class XmlConfigReader{
	private static XmlConfigReader instance=new XmlConfigReader();
	private XmlConfigReader(){
	}
	public static XmlConfigReader getInstance(){
		return instance;
	}
}


懒汉式(延迟初始化对象)

//懒汉式(延迟加载lazy)
Class XmlConfigReader{   
	 private static XmlConfigReader instance =null;
	    public static synchronized XmlConfigReader getInstance(){
			if(instance==null){
				instance=new XmlConfigReader();
			}
			return instance;
		}
}


我们常常听到"Double-Check Locking"即"双重锁定"的概念,这是因为还有一种加锁方式,即使用Lock.

Class XmlConfigReader{
	 private static XmlConfigReader instance;
	private static readonly object syncRoot=new object();
	private XmlConfigReader(){
	}
	public static XmlConfigReader getInstance(){
	             
		if(instance==null){
			Lock( syncRoot) { 
				if(instance==null){
					instance=new XmlConfigReader();
				}
			}
		}
		return instance;
	}
}


对比:
单例模式分两类,这种静态初始化的方式是在类被加载时实例化,与懒汉式的第一次被引用时才实例化相比提前占用系统资源;但懒汉式需要加锁保证多线程访问的安全性,饿汉式却不需要.我们只好择其善者而用之…

项目中的单例应用:
DRP中几乎每个模块都有Manager,在系统开发的初期,因为只有ClientManager,使用单例模式如下:
public class ClientManager {
	private static ClientManager instance=new ClientManager();

	private ClientManager(){}
	
	public static ClientManager getInstance(){
		return instance;
	}
}


随着系统复杂度的增加,出现越来越多的Manager,如ItemManager,FlowCardManager等,而且这时候Manager与Dao进行了分离,出现了分层.系统采用了抽象工厂+反射技术实现Manager类和Dao类的实例化.单例又被应用在工厂中.

public class BeanFactory {

	private static BeanFactory instance=new BeanFactory();
	
	private final String beansConfigFile="beans-config.xml";
	
	private Document doc;

	private BeanFactory(){
		try {			
			doc=new SAXReader().read(Thread.currentThread().getContextClassLoader().getResourceAsStream(beansConfigFile));
		} catch (DocumentException e) {
			e.printStackTrace();
			throw new RuntimeException();
		}
	}
	
	public static BeanFactory getInstance(){
		return instance;
	}
}


以下这段代码是工厂类中得到Manager的单例实现的一部分.开始还真以为是享元模式,后来发现这个实现比享元模式还要灵活.它能保证对象只有一个实例,因此还是单例模式的应用.越到后面用到的东西越多,已经不仅仅局限于某一个模式或技术了,享元,单例,工厂,代理……

//保存Service相关对象
private Map serviceMap=new HashMap();
/**
	 * 根据产品编号取得service系列产品
	 * @param beanId
	 * @return
	 */
	public synchronized Object getServiceObject(Class c){
		//如果存在相关对象实例,返回
		if(serviceMap.containsKey(c.getName())){
			return serviceMap.get(c.getName());
		}
		Element beanElt=(Element)doc.selectSingleNode("//service[@id=\"" + c.getName() +"\"]");
		String className=beanElt.attributeValue("class");
		Object service=null;
		try {
			service=Class.forName(className).newInstance();
			//将创建好的对象放到map中
			serviceMap.put(c.getName(), service);
			
		} catch (Exception e) {
			throw new RuntimeException();
		}
		return service;
	}


通过以上分析和应用,再看单例模式的重点:
实现上,私有静态成员变量/私有构造方法/公共的静态方法;解决了全局访问和实例化控制的问题.
单例的意义不在于创建,而在于访问,也就是说,要访问或调用的对象如果不存在就创建一个,这是唯一一个,之后不能再创建;如果存在就返回该对象,尽管该对象的属性因为被重新赋值改变过无数次,对象是唯一的但不是一成不变的.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: