Java單例模式簡單介紹
一、概念
單例模式是一種常用的軟件設(shè)計(jì)模式。在它的核心結(jié)構(gòu)中只包含一個(gè)被稱為單例類的特殊類。通過單例模式可以保證系統(tǒng)中一個(gè)類只有一個(gè)實(shí)例而且該實(shí)例易于外界訪問,從而方便對(duì)實(shí)例個(gè)數(shù)的控制并節(jié)約系統(tǒng)資源。如果希望在系統(tǒng)中某個(gè)類的對(duì)象只能存在一個(gè),單例模式是最好的解決方案。就筆者認(rèn)為,單例就是不讓外界創(chuàng)建對(duì)象。
1.1概念剖析
對(duì)于單例的話,從上面的概念剖析,應(yīng)該滿足下面的幾個(gè)條件:
第一:單例類中只能有一個(gè)單例對(duì)象;
第二:單例類必須自己創(chuàng)建自己的唯一實(shí)例對(duì)象;
第三:這個(gè)實(shí)例對(duì)象能夠給外界訪問到,并且外界不能夠自己創(chuàng)建對(duì)象。
二、常見幾種單例模式的方式
在java中,對(duì)于單例模式一般來說,分為懶漢式,餓漢式,以及登記式,但是登記式一般較少看到,所以也容易忽略。筆者若非今天突然想總結(jié)一下,在網(wǎng)上查找資料,也不會(huì)注意到這個(gè)。下面按照這種方式來貼出代碼,并進(jìn)行解釋。
2.1餓漢式單例類
package com.ygh.singleton;
/**
* 餓漢式單例類
* @author 夜孤寒
* @version 1.1.1
*/
public class HungerSingleton {
//將構(gòu)造方法私有,外界類不能使用構(gòu)造方法new對(duì)象
private HungerSingleton(){}
//創(chuàng)建一個(gè)對(duì)象
private static final HungerSingleton lazySinleton=new HungerSingleton();
//設(shè)置實(shí)例獲取方法,返回實(shí)例給調(diào)用者
public static HungerSingleton getInstance(){
return lazySinleton;
}
}
寫一個(gè)測試類,測試是不是實(shí)現(xiàn)單例:
package com.ygh.singleton;
/**
* 測試單例類
*
* @author 夜孤寒
* @version 1.1.1
*/
public class Test {
public static void main(String[] args) {
/*
* 構(gòu)造方法私有化,不能夠使用下面方式new對(duì)象
*/
//HungerSingleton hungerSingleton=new HungerSingleton();
//使用實(shí)例獲取方法來獲取對(duì)象
HungerSingleton h1=HungerSingleton.getInstance();
HungerSingleton h2=HungerSingleton.getInstance();
System.out.println(h1==h2);//true
}
}
從上面可以看出:這個(gè)測試類的兩個(gè)引用是相等的,也就是說兩個(gè)引用指向的是同一個(gè)對(duì)象,而這也正好符合單例模式標(biāo)準(zhǔn)。到這里,餓漢式介紹結(jié)束。
2.2餓漢式單例類
package com.ygh.singleton;
/**
* 懶漢式單例類
* @author 夜孤寒
* @version 1.1.1
*/
public class LazySingleton {
//將構(gòu)造方法私有,外界類不能使用構(gòu)造方法new對(duì)象
private LazySingleton(){}
//創(chuàng)建一個(gè)對(duì)象,不為final
private static LazySingleton lazySingleton=null;
//設(shè)置實(shí)例獲取方法,返回實(shí)例給調(diào)用者
public static LazySingleton getInstance(){
//當(dāng)單例對(duì)象不存在,創(chuàng)建
if(lazySingleton==null){
lazySingleton=new LazySingleton();
}
//返回
return lazySingleton;
}
}
測試類:
package com.ygh.singleton;
/**
* 測試單例類
*
* @author 夜孤寒
* @version 1.1.1
*/
public class Test {
public static void main(String[] args) {
/*
* 構(gòu)造方法私有化,不能夠使用下面方式new對(duì)象
*/
//LazySingleton lazySingleton=new LazySingleton();
//使用實(shí)例獲取方法來獲取對(duì)象
LazySingleton l1=LazySingleton.getInstance();
LazySingleton l2=LazySingleton.getInstance();
System.out.println(l1==l2);//true
}
}
從上面可以看出:這個(gè)測試類的兩個(gè)引用是相等的,也就是說兩個(gè)引用指向的是同一個(gè)對(duì)象,而這也正好符合單例模式標(biāo)準(zhǔn)。到這里,懶漢式介紹結(jié)束。
2.3懶漢式和餓漢式的區(qū)別
懶漢式是當(dāng)沒有對(duì)象的時(shí)候,就會(huì)創(chuàng)建一個(gè)單例對(duì)象,當(dāng)有對(duì)象的時(shí)候,就不會(huì)再創(chuàng)建對(duì)象,這個(gè)說起來可能不是那么容易理解,但是讀者如果有興趣了解更深,可以在eclipse中使用斷點(diǎn)來測試,將LazySingleton類的if花括號(hào)內(nèi)的內(nèi)容加上斷點(diǎn),然后在Test類中,使用debug運(yùn)行,這樣子就能夠很容易體現(xiàn)出來,第一次創(chuàng)建了一個(gè)對(duì)象,但是第二次沒有創(chuàng)建對(duì)象。
餓漢式則是實(shí)現(xiàn)就用final這個(gè)關(guān)鍵字將對(duì)象創(chuàng)建好了,當(dāng)調(diào)用者需要實(shí)例對(duì)象的時(shí)候,就可以通過getInstance這個(gè)方法獲取創(chuàng)建好的實(shí)例。
2.4登記式單例類
對(duì)于登記式單例類,筆者也不是很熟悉,貼了一段網(wǎng)絡(luò)上的代碼以供自己學(xué)習(xí)參考,請(qǐng)讀者自行學(xué)習(xí)。
import java.util.HashMap;
import java.util.Map;
/**
* 登記式單例類
* @author Administrator
*
*/
public class RegisterSingleton {
private static Map<String, RegisterSingleton> map = new HashMap<String, RegisterSingleton>();
static {
RegisterSingleton single = new RegisterSingleton();
map.put(single.getClass().getName(), single);
}
/*
* 保護(hù)的默認(rèn)構(gòu)造方法
*/
protected RegisterSingleton() {
}
/*
* 靜態(tài)工廠方法,返還此類惟一的實(shí)例
*/
public static RegisterSingleton getInstance(String name) {
if (name == null) {
name = RegisterSingleton.class.getName();
System.out.println("name == null" + "--->name=" + name);
}
if (map.get(name) == null) {
try {
map.put(name, (RegisterSingleton) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
/*
* 一個(gè)示意性的商業(yè)方法
*/
public String about() {
return "Hello, I am RegSingleton.";
}
public static void main(String[] args) {
RegisterSingleton single3 = RegisterSingleton.getInstance(null);
System.out.println(single3.about());
}
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
聊聊@Autowired注解注入,寫接口名字還是實(shí)現(xiàn)類的名字
這篇文章主要介紹了聊聊@Autowired注解注入,寫接口名字還是實(shí)現(xiàn)類的名字,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Spring AOP攔截-三種方式實(shí)現(xiàn)自動(dòng)代理詳解
這篇文章主要介紹了Spring AOP攔截-三種方式實(shí)現(xiàn)自動(dòng)代理詳解,還是比較不錯(cuò)的,這里分享給大家,供需要的朋友參考。2017-11-11
SpringBoot實(shí)現(xiàn)熱部署的三種方式
本文主要介紹了SpringBoot實(shí)現(xiàn)熱部署的三種方式,主要包括配置pom.xml文件,使用插件的執(zhí)行命令mvn spring-boot:run啟動(dòng)項(xiàng),使用springloader本地啟動(dòng)修改jvm參數(shù),使用devtools工具包,感興趣的可以了解一下2023-12-12
mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的方法
這篇文章主要給大家介紹了關(guān)于mybatis攔截器實(shí)現(xiàn)通用權(quán)限字段添加的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Java常見延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié)
Java延遲隊(duì)列(DelayQueue)是Java并發(fā)包中的一個(gè)類,它實(shí)現(xiàn)了BlockingQueue接口,且其中的元素必須實(shí)現(xiàn)Delayed接口,延遲隊(duì)列中的元素按照延遲時(shí)間的長短進(jìn)行排序,本文給大家介紹了Java常見延遲隊(duì)列的實(shí)現(xiàn)方案總結(jié),需要的朋友可以參考下2024-03-03
代理模式之Java動(dòng)態(tài)代理實(shí)現(xiàn)方法
今天一個(gè)偶然的機(jī)會(huì)我突然想看看JDK的動(dòng)態(tài)代理,因?yàn)橐郧耙仓酪稽c(diǎn),而且只是簡單的想測試一下使用,使用很快里就寫好了這么幾個(gè)接口和類,需要的朋友可以參考下2012-11-11

