首页 > 代码库 > Java项目(5)——单例模式的应用与研究
Java项目(5)——单例模式的应用与研究
单例模式是很别致的一个模式,很少有人拿它跟其他模式相比,因为,单例模式很简单,很特别,作用就是保证一个类有唯一一个实例,并让一个全局变量使得它能被访问.而保证这个类只被实例化一次的办法就是把构造函数变为私有的,除了它自己都不能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; }
通过以上分析和应用,再看单例模式的重点:
实现上,私有静态成员变量/私有构造方法/公共的静态方法;解决了全局访问和实例化控制的问题.
单例的意义不在于创建,而在于访问,也就是说,要访问或调用的对象如果不存在就创建一个,这是唯一一个,之后不能再创建;如果存在就返回该对象,尽管该对象的属性因为被重新赋值改变过无数次,对象是唯一的但不是一成不变的.
Java项目(5)——单例模式的应用与研究
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。