程序员人生 网站导航

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

栏目:互联网时间:2014-11-05 08:44:45

       单例模式是很新颖的1个模式,很少有人拿它跟其他模式相比,由于,单例模式很简单,很特别,作用就是保证1个类有唯逐一个实例,并让1个全局变量使得它能被访问.而保证这个类只被实例化1次的办法就是把构造函数变成私有的,除它自己都不能new新对象,然后把实例化的进程写在类本身的公有方法里,是不是new新对象只有它自己判断决定,已有了1个实例就直接返回已存在的对象,没有就new1个新实例.其他类想实例化1个对象时调这个公有方法.

  • 饿汉式(预先初始化对象
//饿汉式 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""两重锁定"的概念,这是由于还有1种加锁方式,即便用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; } }

对照:

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

 

项目中的单例利用:

         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的单例实现的1部份.开始还真以为是享元模式,后来发现这个实现比享元模式还要灵活.它能保证对象只有1个实例,因此还是单例模式的利用.越到后面用到的东西越多,已不单单局限于某1个模式或技术了,享元,单例,工厂,代理……


//保存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; }


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

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

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


------分隔线----------------------------
------分隔线----------------------------

最新技术推荐