• 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;
    	}


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

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

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


  • 相关阅读:
    代码品质
    窖藏好题
    最后一次模拟
    几个有意思的题目
    【数组练习】
    【复习】图论
    【复习】后缀数组
    The Usage Of Difference Table
    【复习】NTT注意事项
    CF999E Reachability from the Capital
  • 原文地址:https://www.cnblogs.com/slgkaifa/p/6728690.html
Copyright © 2020-2023  润新知