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

       单例模式是非常别致的一个模式,非常少有人拿它跟其它模式相比,由于,单例模式非常easy,非常特别,作用就是保证一个类有唯一一个实例,并让一个全局变量使得它能被訪问.而保证这个类仅仅被实例化一次的办法就是把构造函数变为私有的,除了它自己都不能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,并且这时候ManagerDao进行了分离,出现了分层.系统採用了抽象工厂+反射技术实现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;
	}


        通过以上分析和应用,再看单例模式的重点:

        实现上,私有静态成员变量/私有构造方法/公共的静态方法;攻克了全局訪问和实例化控制的问题.

       单例的意义不在于创建,而在于訪问,也就是说,要訪问或调用的对象假设不存在就创建一个,这是唯一一个,之后不能再创建;假设存在就返回该对象,虽然该对象的属性由于被又一次赋值改变过无数次,对象是唯一的但不是一成不变的.


原文地址:https://www.cnblogs.com/slgkaifa/p/6728690.html