Java設(shè)計(jì)模式之單件模式深入講解
定義
單件模式確保一個(gè)類(lèi)只有一個(gè)實(shí)例,并提供一個(gè)全局訪(fǎng)問(wèn)點(diǎn)
Java單件模式
經(jīng)典單件模式的實(shí)現(xiàn)
public class Singleton{ private static Singleton uniqueInstance; // 利用一個(gè)靜態(tài)變量來(lái)記錄Singleton類(lèi)的唯一實(shí)例 private Singleton(){} // 把構(gòu)造器聲明為私有的,只有自Singleton類(lèi)內(nèi)才可以調(diào)用構(gòu)造器 // 用getInstance()方法實(shí)例化對(duì)象,并返回這個(gè)實(shí)例 public static Singleton getInstance(){ if (uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }
在多線(xiàn)程中以上代碼會(huì)生成多個(gè)實(shí)例,所以需要我們對(duì)代碼進(jìn)行改進(jìn)
多線(xiàn)程單件模式的實(shí)現(xiàn)
public class Singleton{ private static Singleton uniqueInstance; private Singleton(){} public static synchronized Singleton getInstance(){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } return uniqueInstance; } }
通過(guò)增加synchronized關(guān)鍵字到getInstance()方法中,我們迫使每個(gè)線(xiàn)程在進(jìn)入這個(gè)方法之前,要先等候別的線(xiàn)程離開(kāi)該方法。也就是說(shuō),不會(huì)有兩個(gè)線(xiàn)程可以同時(shí)進(jìn)入這個(gè)方法。
急切創(chuàng)建實(shí)例
public class Singleton{ // 在靜態(tài)初始化器(static initializai)中創(chuàng)建單件。這樣可以保證線(xiàn)程安全(thread sate) private static Singleton uniqueInstance = new Singleton(); private static Singleton getInstance(){ return uniqueInstance; } }
在JVM在加載這個(gè)類(lèi)時(shí)馬上創(chuàng)建此唯一的單件實(shí)例。JVM保證在任何線(xiàn)程訪(fǎng)問(wèn)uniqueInstance靜態(tài)變量之前,一定創(chuàng)建此實(shí)例。
雙重檢查加鎖
會(huì)有兩次檢查實(shí)例是否存在,若不存在則創(chuàng)建實(shí)例,若存在則返回
public class Singlenton{ // volatile關(guān)鍵詞:當(dāng)uniqueInstance變量被初始化成Singleton實(shí)例時(shí),多個(gè)線(xiàn)程正確地處理uniqueInstance變量 private volatile static Singleton uniqueInstance(); private Singleton(){} public static Singleton getInstance(){ // 檢查實(shí)例,如果不存在,就進(jìn)入同步區(qū)塊 if(uniqueInstance == null){ // 進(jìn)入?yún)^(qū)塊后,再檢查一次。如果仍是null,才創(chuàng)建實(shí)例 synchronized (Singleton.class){ if(uniqueInstance == null){ uniqueInstance = new Singleton(); } } } return uniqueInstance; } }
Python單件模式
模塊實(shí)現(xiàn)
Python 的模塊就是天然的單件模式,在模塊第一次被導(dǎo)入時(shí),會(huì)生成.pyc文件,之后再次導(dǎo)入時(shí),就會(huì)直接加載之前生成的.pyc文件,不會(huì)再次執(zhí)行模塊代碼
先創(chuàng)建一個(gè)Singleton文件
class Singleton: def getSingleton: pass singleton = Singleton()
在其他文件中導(dǎo)入這個(gè)模塊,這個(gè)類(lèi)的地址是唯一的
new關(guān)鍵字實(shí)現(xiàn)
當(dāng)實(shí)例化一個(gè)對(duì)象時(shí),先調(diào)用類(lèi)的__new__方法 ,默認(rèn)調(diào)用的是父類(lèi)Object.__new__方法,實(shí)例化對(duì)象。然后再調(diào)用類(lèi)的__init__方法進(jìn)行屬性的初始化。
我們可以再__new__方法內(nèi)加一個(gè)判斷,若實(shí)例存在,則不實(shí)例化,若不存在,則實(shí)例化。
class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if cls._instance is None: cls._instance = object.__new__(cls, *args, **kwargs) return cls._instance def __init__(self): pass
裝飾器實(shí)現(xiàn)
通過(guò)裝飾器來(lái)實(shí)現(xiàn)單件模式
函數(shù)裝飾器
def singleton(cls): # 創(chuàng)建一個(gè)私有變量,類(lèi)型為字典,用來(lái)存放類(lèi)地址的 _instance = {} def inner(): # 如果類(lèi)不存在 if cls not in _instance: # 實(shí)例化一個(gè)類(lèi)并存放在字典里 _instance[cls] = cls() return _instance[cls] return inner @singleton class ClassName(object): def __init__(self): pass
類(lèi)裝飾器
class Singleton(object): def __init__(self, cls): self._cls = cls # 接受類(lèi)名 self._instance = {} # 存放類(lèi)地址 def __call__(self): if self._cls not in self._instance: # 實(shí)例化類(lèi)并存放在字典內(nèi) self._instance[self._cls] = self._cls() return self._instance[self._cls] @Singleton class ClassName(object): def __init__(self): pass
以上就是Java設(shè)計(jì)模式之單件模式深入講解的詳細(xì)內(nèi)容,更多關(guān)于Java設(shè)計(jì)模式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java線(xiàn)程池實(shí)現(xiàn)批量下載文件
這篇文章主要為大家詳細(xì)介紹了java線(xiàn)程池實(shí)現(xiàn)批量下載文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-07-07springboot+thymeleaf國(guó)際化之LocaleResolver接口的示例
本篇文章主要介紹了springboot+thymeleaf國(guó)際化之LocaleResolver的示例 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11Java基于HttpClient實(shí)現(xiàn)RPC的示例
HttpClient可以實(shí)現(xiàn)使用Java代碼完成標(biāo)準(zhǔn)HTTP請(qǐng)求及響應(yīng)。本文主要介紹了Java基于HttpClient實(shí)現(xiàn)RPC,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10mybatis中string和date的轉(zhuǎn)換方式
這篇文章主要介紹了mybatis中string和date的轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Java 基礎(chǔ)全面講解StringBuffer類(lèi)的使用
當(dāng)對(duì)字符串進(jìn)行修改的時(shí)候,需要使用 StringBuffer 和 StringBuilder類(lèi),和String類(lèi)不同的是,StringBuffer和 StringBuilder類(lèi)的對(duì)象能夠被多次的修改,并且不產(chǎn)生新的未使用對(duì)象2022-01-01Logback配置文件這么寫(xiě),還說(shuō)你不會(huì)整理日志?
logback框架會(huì)默認(rèn)加載classpath下命名為logback-spring.xml或logback.xml的配置文件。這篇文章主要介紹了Logback配置文件寫(xiě)法,需要的朋友可以參考下2020-07-07詳解SpringBoot開(kāi)發(fā)案例之整合定時(shí)任務(wù)(Scheduled)
本篇文章主要介紹了詳解SpringBoot開(kāi)發(fā)案例之整合定時(shí)任務(wù)(Scheduled),具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07Java實(shí)戰(zhàn)入門(mén)之雙色球彩票小游戲
這篇文章主要介紹了Java實(shí)戰(zhàn)入門(mén)之雙色球彩票,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04