設計模式-單例模式
定義
單例模式(singleton pattern)是確保一個類在任何情況下都絕對只有一個實例,并提供一個全局訪問點。
單例模式是創(chuàng)建型模式。
分類
1、餓漢式(餓漢和靜態(tài)餓漢)
2、懶漢式(線程安全要加鎖)
3、枚舉式(注冊)初始化即生成,餓漢式,可以保證不被反射機制和反序列化破壞,是借助JDK的特性,所以最官方、最權威、最穩(wěn)定
4、序列化單例模式(可以解決反序列化問題,但是內存開銷依然很大)
5、容器式單例模式(容器式單例模式適用于需要大量創(chuàng)建單例對象的場景,便于管理。但它是非線程安全的)
6、threadLocal單例模式(不能保證其創(chuàng)建的對象是全局唯一的,但是能保證在單個線程中是唯一的,天生是線程安全的)
總結
????單例模式可以保證內存中只有一個實例,減少了內存開銷,還可以避免對資源的多重占用。
單例模式的常見應?場景
單例模式(Singleton)也叫單態(tài)模式,是設計模式中最為簡單的?種模式,甚?有些模式?師都不稱其為模式,稱其為?種實現(xiàn)技巧,因為設計模式講究對象之間的關系的抽象,?單例模式只有???個對象,也因此有些設計?師并把把其稱為設計模式之?。
好多沒怎么使?過的?可能會想,單例模式感覺不怎么?到,實際的應?場景有哪些呢?以下,我將列出?些就在咱們周邊和很有意義的單例應?場景。
1. Windows的Task Manager(任務管理器)就是很典型的單例模式(這個很熟悉吧),想想看,是不是呢,你能打開兩個windows task manager嗎? 不信你??試試看哦~
2. windows的Recycle Bin(回收站)也是典型的單例應?。在整個系統(tǒng)運?過程中,回收站?直維護著僅有的?個實例。
3. ?站的計數(shù)器,?般也是采?單例模式實現(xiàn),否則難以同步。
4. 應?程序的?志應?,?般都何?單例模式實現(xiàn),這?般是由于共享的?志?件?直處于打開狀態(tài),因為只能有?個實例去操作,否則內容不好追加。
5. Web應?的配置對象的讀取,?般也應?單例模式,這個是由于配置?件是共享的資源。
6. 數(shù)據(jù)庫連接池的設計?般也是采?單例模式,因為數(shù)據(jù)庫連接是?種數(shù)據(jù)庫資源。數(shù)據(jù)庫軟件系統(tǒng)中使?數(shù)據(jù)庫連接池,主要是節(jié)省打開或者關閉數(shù)據(jù)庫連接所引起的效率損耗,這種效率上的損耗還是?常昂貴的,因為何?單例模式來維護,就可以??降低這種損耗。
7. 多線程的線程池的設計?般也是采?單例模式,這是由于線程池要?便對池中的線程進?控制。
8. 操作系統(tǒng)的?件系統(tǒng),也是?的單例模式實現(xiàn)的具體例?,?個操作系統(tǒng)只能有?個?件系統(tǒng)。
9. HttpApplication 也是單位例的典型應?。熟悉ASP.Net(IIS)的整個請求?命周期的?應該知道HttpApplication也是單例模式,所有的HttpModule都共享?個HttpApplication實例.
? 總結以上,不難看出:
單例模式應?的場景?般發(fā)現(xiàn)在以下條件下:
(1)資源共享的情況下,避免由于資源操作時導致的性能或損耗等。如上述中的?志?件,應?配置。
(2)控制資源的情況下,?便資源之間的互相通信。如線程池等。
單例模式優(yōu)點:
1、在內存中只有一個實例,減少了內存開銷。
2、可以避免資源的多重占用。
3、設置全局訪問點,嚴格控制訪問。
單例模式的缺點:
1、沒有接口,擴展困難。
2、如果要擴展單例對象,只有修改代碼,沒有其他途徑。
代碼實例









學習單例模式的知識重點總結
1、私有化構造器
2、保證線程安全
單例模式可以保證內存里只有一個實例,減少了內存的開銷,還可以避免對資源的多重占用。單例模式看起來非常簡單,實現(xiàn)起來其實也非常簡單,但是在面試中卻是一個高頻面試點。希望“小伙伴們”通過本章的學習,對單例模式有了非常深刻的認識,在面試中彰顯技術深度,提升核心競爭力,給面試加分,順利拿到錄取通知(Offer)。
擴展
1、解決容器式單例的線程安全問題。
兩種方法:雙重檢查鎖,利用ConcurrentHashMap#putIfAbsent()方法的原子性。
public class ContainerSingleton {
????private static Map ioc = new ConcurrentHashMap();
????private ContainerSingleton() {
? ? ? ? ????throw new RuntimeException("不可被實例化!");
????}
? ? // 方法一:雙重檢查鎖
????public static Object getInstance(String className) {
????????Object instance = null;
????????if (!ioc.containsKey(className)) {
????????????synchronized (ContainerSingleton.class) {
????????????????if (!ioc.containsKey(className)) {
????????????????????try {
????????????????????????instance = Class.forName(className).newInstance();
????????????????????????ioc.put(className, instance);
? ? ? ? ? ? ? ? ? ? } catch (Exception e) {
????????????????????????e.printStackTrace();
????????????????????}
????????????????return instance;
????????????????} else {
????????????????????return ioc.get(className);
????????????????}
????????????}
????????}
????????return ioc.get(className);
????}
? ? // 方法二:利用ConcurrentHashMap#putIfAbsent()方法的原子性
public static Object getInstance1(String className){
????Object instance = null;
????try {
????????ioc.putIfAbsent(className, Class.forName(className).newInstance());
????}catch (Exception e){
????????e.printStackTrace();
????}
????return ioc.get(className);
????}
}