Java項目(5)――單例模式的應用與研究
來源:程序員人生 發布時間:2014-11-05 08:44:45 閱讀次數:2317次
單例模式是很新穎的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等,而且這時候候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的單例實現的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成不變的.
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈