/**
* 作者:wanglei
* 郵箱:229846388@qq.com
* 單例模式
* Singleton.單例模式的一般實現(xiàn)
* 分類說明:
* 1.餓漢式:類加載時 自動初始化 單例
* 2.懶漢式:有需要的時候才手動調(diào)用 getInstance()初始化單例
* 區(qū)別:
* 1.懶漢式與餓漢式最大的區(qū)別是單例的初始化操作的時機(jī):
* 多線程下的單例模式實現(xiàn):
* 1.對于 餓漢式:多線程下適用,因為JVM只會加載一次單例類;
* 2.對于 懶漢式:多線程不適用,因為在創(chuàng)建單例時是線程不安全的。
* 3.即,多個線程可能會并發(fā)調(diào)用 newInstance (),從而重復(fù)創(chuàng)建單例對象
*/
/**
* 餓漢式
* 應(yīng)用場景:
* 1.應(yīng)用啟動時,需自動加載 & 初始化單例
* 2.單例對象要求初始化速度非常快且占用內(nèi)存非常小
*/
classHungryManSingleton{
/**
* 創(chuàng)建私有變量 instance(用以記錄 Singleton 的唯一實例)
* 內(nèi)部進(jìn)行實例化
*/
private staticHungryManSingletoninstance=newHungryManSingleton();
/**
* 把類的構(gòu)造方法私有化,不讓外部調(diào)用構(gòu)造方法實例化
*/
privateHungryManSingleton(){
}
/**
* 定義公有方法提供該類的全局唯一訪問點
*@return外部通過調(diào)用getInstance()方法來返回唯一的實例
*/
public staticHungryManSingletongetInstance(){
returninstance;
}
}
/**
* 懶漢式
* 應(yīng)用場景:
* 1.單例初始化的操作耗時長 & 應(yīng)用要求啟動速度快
* 2.單例的占用內(nèi)存比較大
* 3.單例只是在某個特定場景的情況下才會被使用,即按需延遲加載單例
*/
classLazyManSingleton{
/**
* 先賦值為Null,需要時才手動調(diào)用 getInstance() 創(chuàng)建
*/
private staticLazyManSingletoninstance=null;
privateLazyManSingleton(){
}
/**
* 先判斷單例是否為空,以避免重復(fù)創(chuàng)建
*@return外部通過調(diào)用getInstance()方法來返回唯一的實例
*/
public staticLazyManSingletongetInstance(){
if(instance==null){
instance=newLazyManSingleton();
}
returninstance;
}
}
/**
* 多線程下的單例模式實現(xiàn):
* 懶漢式
* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行
* 解決方案1:
* 1.同步鎖
* 2.使用同步鎖 synchronized (Singleton.class) ,防止多線程同時進(jìn)入,從而造成instance被多次實例化
* 缺點:
* 1.該解決方案的缺點在于:加鎖 = 非常耗時操作,耗時耗能
*/
classMultithreadingLazyManSingleton1{
private staticMultithreadingLazyManSingleton1instance=null;
privateMultithreadingLazyManSingleton1(){}
public staticMultithreadingLazyManSingleton1getInstance(){
/**
* 加入同步鎖
*/
synchronized(MultithreadingLazyManSingleton1.class){
if(instance==null){
instance=newMultithreadingLazyManSingleton1();
}
}
returninstance;
}
}
/**
* 多線程下的單例模式實現(xiàn):
* 懶漢式
* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行
* 解決方案2:
* 1.雙重校驗鎖
* 2.在同步鎖的基礎(chǔ)上,添加1層 if判斷:若Instance已實例化,則不必執(zhí)行加鎖操作就可以獲取實例,從而提高性能
* 缺點:
* 1.實現(xiàn)復(fù)雜 = 多種判斷,易出錯
*/
classMultithreadingLazyManSingleton2{
private staticMultithreadingLazyManSingleton2intance=null;
privateMultithreadingLazyManSingleton2(){}
public staticMultithreadingLazyManSingleton2getIntance(){
/**
* 在同步鎖的基礎(chǔ)上,添加1層if判斷 若單例已創(chuàng)建,則直接跳到執(zhí)行 return ourInstance
*/
if(intance==null){
synchronized(MultithreadingLazyManSingleton2.class){
if(intance==null){
intance=newMultithreadingLazyManSingleton2();
}
}
}
returnintance;
}
}
/**
* 多線程下的單例模式實現(xiàn):
* 懶漢式
* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行
* 解決方案3:
* 1.靜態(tài)內(nèi)部類
* 2.在內(nèi)部類里面去創(chuàng)建對象實例
*/
classMultithreadingLazyManSingleton3{
/**
* 在內(nèi)部類里面去創(chuàng)建對象實例對象;在裝載該內(nèi)部類時才會去創(chuàng)建單例
* 線程安全:類是由JVM加載的,而JVM只會加載一遍,保證只有1個單例模式,保證了數(shù)據(jù)同步
*/
private static classSingleton{
private staticSingletoninstance=newSingleton();
/**
* 私有構(gòu)造函數(shù)
*/
privateSingleton(){}
/**
*@return延遲加載、按需創(chuàng)建:外部調(diào)用類getInstance() ->調(diào)用Singleton.instance -> 創(chuàng)建實例
*/
public staticSingletongetInstance(){
returnSingleton.instance;
}
}
}
/**
* 多線程下的單例模式實現(xiàn):
* 懶漢式
* 1.下面,將對懶漢式 進(jìn)行優(yōu)化,使得適合在多線程環(huán)境下運行
* 解決方案4:
* 1.枚舉類型
* 2.最簡潔、易用的單例實現(xiàn)方式,(《Effective Java》推薦)
* 使用方式:
* MultithreadingLazyManSingleton4 singleton = MultithreadingLazyManSingleton4.instance;
* singleton.doSomething();
*/
enumMultithreadingLazyManSingleton4{
/**
* 定義一個枚舉的元素,它就是MultithreadingLazyManSingleton4的一個實例instance;
*/
instance;
public voiddoSomething(){
}
}
舉例說明:
/**
* 作者:wanglei
* 郵箱:229846388@qq.com
* 單例模式
* 單例倉庫類
*/
public classStoreHouse {
/**
* 倉庫商品數(shù)量
*/
private intquantity=100;
/**
* //自己在內(nèi)部實例化
*/
private staticStoreHouseinstance=newStoreHouse();
/**
* 封閉構(gòu)造函數(shù)
*/
privateStoreHouse(){
}
/**
*@return讓外部通過調(diào)用getInstance()方法來返回唯一的實例。
*/
public staticStoreHousegetInstance(){
returninstance;
}
public intgetQuantity() {
returnquantity;
}
public voidsetQuantity(intquantity) {
this.quantity= quantity;
}
}
/**
* 作者:wanglei
* 郵箱:229846388@qq.com
* 單例模式
* 搬貨工人類
*/
public classCarrier {
publicStoreHousemStoreHouse;
publicCarrier(StoreHouse storeHouse){
mStoreHouse= storeHouse;
}
/**
* 搬貨進(jìn)倉庫
*@parami
*/
public voidmoveIn(inti){
mStoreHouse.setQuantity(mStoreHouse.getQuantity() + i);
}
/**
* 搬貨出倉庫
*@parami
*/
public voidMoveOut(inti){
mStoreHouse.setQuantity(mStoreHouse.getQuantity() - i);
}
}
/**
* 作者:wanglei
* 郵箱:229846388@qq.com
* 單例模式
* 解決的問題:
* 1.降低對象之間的耦合度
* 解決方法:
* 1.實現(xiàn)一個類只有一個實例化對象,并提供一個全局訪問點
*/
public classSimpleSinglePattern {
public static voidmain(String[] args){
StoreHouse storeHouse1 = StoreHouse.getInstance();
StoreHouse storeHouse2 = StoreHouse.getInstance();
Carrier carrier1 =newCarrier(storeHouse1);
Carrier carrier2 =newCarrier(storeHouse2);
System.out.println("兩個是不是同一個?");
if(storeHouse1.equals(storeHouse2)){
System.out.println("YES");
}else{
System.out.println("NO");
}
//搬運工搬完貨物之后出來匯報倉庫商品數(shù)量
carrier1.moveIn(30);
System.out.println("倉庫商品余量:"+ carrier1.mStoreHouse.getQuantity());
carrier2.MoveOut(50);
System.out.println("倉庫商品余量:"+ carrier2.mStoreHouse.getQuantity());
}
}
/**
* 結(jié)果:
* 兩個是不是同一個?
* YES
* 倉庫商品余量:130
* 倉庫商品余量:80
* 優(yōu)點:
* 1.提供了對唯一實例的受控訪問;
* 2.由于在系統(tǒng)內(nèi)存中只存在一個對象,因此可以節(jié)約系統(tǒng)資源,對于一些需要頻繁創(chuàng)建和銷毀的對象單例模式無疑可以提高系統(tǒng)的性能;
* 3.可以根據(jù)實際情況需要,在單例模式的基礎(chǔ)上擴(kuò)展做出雙例模式,多例模式;
* 缺點:
* 1.單例類的職責(zé)過重,里面的代碼可能會過于復(fù)雜,在一定程度上違背了“單一職責(zé)原則”。
* 2.如果實例化的對象長時間不被利用,會被系統(tǒng)認(rèn)為是垃圾而被回收,這將導(dǎo)致對象狀態(tài)的丟失。
*/
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。