1. 程式人生 > >小菜學習設計模式(二)—單例(Singleton)模式

小菜學習設計模式(二)—單例(Singleton)模式

前言

設計模式目錄:

本篇目錄:

  單例模式(Singleton)可以說是最簡單的模式,對.net來說,因為不需要考慮到垃圾回收機制,實現起來很簡單,但是對於沒有提供記憶體管理的平臺來說,比如C++,因為單例模式只考慮建立物件,所以使用的時候要考慮全面些。

  其實說到些設計模式,我們有時候用到的真的很少,就像飛機零部件的模具不適用於汽車製造一樣,某些設計模式也只在特定的環境下使用,單例模式的使用場景一般是資源管理器等,像說的最多的就是印表機場景:每臺計算機可以有若干個印表機,但只能有一個Printer Spooler,以避免兩個列印作業同時輸出到印表機中。每臺計算機可以有若干傳真卡,但是隻應該有一個軟體負責管理傳真卡,以避免出現兩份傳真作業同時傳到傳真卡中的情況。每臺計算機可以有若干通訊埠,系統應當集中管理這些通訊埠,以避免一個通訊埠同時被兩個請求同時呼叫。說白點就是一個男人可以有很多女朋友,但是結婚生子的只能是其中一個。一夫多妻的情況就不是單例模式了,那應該是“多型”了。哈哈。

簡單實現

  單例模式(Singleton)在.net中的定義是:一個類有且僅有一個例項,並且自行例項化向整個系統提供。

從定義中我們可以看出,單例模式所具有的三個要點:

  • 某個類只能有一個例項
  • 必須自行建立這個例項
  • 必須自行向整個系統提供這個例項

  根據所說的要點,我們可以在.net中這樣簡單的實現:

 1     public class SingletonTest
 2     {
 3         public static SingletonTest model;
 4         private SingletonTest()
 5         { }
6 public static SingletonTest getSingleton() 7 { 8 if (model==null) 9 { 10 model = new SingletonTest(); 11 } 12 return model; 13 } 14 }

   程式碼就這麼簡單,在getSingleton()方法返回例項的時候要先判斷物件是否已經被例項化,如果是就不需要重新建立了。

執行緒安全

  上面的程式碼看起來沒什麼問題,但是在多執行緒的情況下就會出現問題,我們來開幾個執行緒測試下:

 1     public class SingletonTest
 2     {
 3         public static SingletonTest model;
 4         private SingletonTest()
 5         { }
 6         public static SingletonTest getSingleton()
 7         {
 8             if (model==null)
 9             {
10                 Console.WriteLine(String.Format("我是被執行緒:{0}建立的!", Thread.CurrentThread.Name));
11                 model = new SingletonTest();
12             }
13             return model;
14         }
15     }
 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Program p1 = new Program();
 6             p1.Test();
 7             Console.ReadLine();
 8         }
 9 
10         private void Test()
11         {
12             Thread newThread;
13             ThreadStart ts = new ThreadStart(DoWork);
14             for (int counter = 1; counter < 6; counter++)
15             {
16                 newThread = new Thread(ts);
17                 newThread.Name = "蟋蟀" + counter;
18                 newThread.Start();
19             }
20         }
21 
22         protected void DoWork()
23         {
24             //呼叫返回物件方法
25             SingletonTest.getSingleton();
26         }
27     }

  執行結果:

  根據上圖的執行結果,會發現SingletonTest物件被例項化了2次,按照單例模式(Singleton)的特性:一個類只能有一個例項,那就不是單例模式了,為什麼會例項化兩次呢?因為我們的計算機執行速度很快,在某一個時間點,執行緒1在執行完if (model==null)這段程式碼,還沒執行model = new SingletonTest(),執行緒2剛好執行判斷物件是否null,就是說執行緒1和執行緒2都會進入下面的if判斷體中例項化物件。

  關於單例模式的執行緒安全問題,網上一找一大堆,在《漫談設計模式》這本書中,作者也提到了執行緒安全問題,java中是使用的是“Double-Check Locking”方法,還有序列化的問題,這邊先不考慮,其實在.net中解決執行緒安全的問題也很簡單,就是用lock鎖,我們根據上面的程式碼,再來修改下,然後做個測試:

 1     public class SingletonTest
 2     {
 3         private static SingletonTest singleton;
 4         private static readonly object syncObject = new object();
 5         /// <summary>
 6         /// 建構函式必須是私有的
 7         /// 這樣在外部便無法使用 new 來建立該類的例項
 8         /// </summary>
 9         private SingletonTest()
10         { }
11         /// <summary>
12         /// 定義一個全域性訪問點
13         /// 設定為靜態方法
14         /// 則在類的外部便無需例項化就可以呼叫該方法
15         /// </summary>
16         /// <returns></returns>
17         public static SingletonTest getSingleton()
18         {
19             //這裡可以保證只例項化一次
20             //即在第一次呼叫時例項化
21             //以後呼叫便不會再例項化
22             //第一重 singleton == null
23             if (singleton == null)
24             {
25                 lock (syncObject)
26                 {
27                     //第二重 singleton == null
28                     if (singleton == null)
29                     {
30                         Console.WriteLine(String.Format("我是被執行緒:{0}建立的!", Thread.CurrentThread.Name));
31                         singleton = new SingletonTest();
32                     }
33                 }
34             }
35             return singleton;
36         }
37     }

   執行結果:

相關推薦

小菜學習設計模式Singleton模式

前言 設計模式目錄: 本篇目錄: 簡單實現 執行緒安全 後記   單例模式(Singleton)可以說是最簡單的模式,對.net來說,因為不需要考慮到垃圾回收機制,實現起來很簡單,但是對於沒有提供記憶體管理的平臺來說,比如C++,因為單例模式只考慮建立物件,所以

設計模式4—— Singleton

導航 首先通過懶漢式的單例模式簡單程式碼實現作為開頭,發現有執行緒安全問題,並且在此懶漢模式程式碼上進行改進,衍生出同步懶漢設計模式,雙重檢查懶漢設計模式。另外還有靜態內部類方式實現單例,它是一種基於類初始化的延遲載入解決方案。 與懶漢式相對應的是餓漢式單例模式

設計模式的征途—1.Singleton模式

  單例模式屬於建立型模式的一種,建立型模式是一類最常用的設計模式,在軟體開發中應用非常廣泛。建立型模式將物件的建立和使用分離,在使用物件時無需關心物件的建立細節,從而降低系統的耦合度,讓設計方案更易於修改和擴充套件。每一個建立型模式都在檢視回答3個問題:3W -> 建立什麼(What)、由誰建立(Wh

Java併發程式設計中的設計模式解析()一個的七種寫法

Java單例模式是最常見的設計模式之一,廣泛應用於各種框架、中介軟體和應用開發中。單例模式實現起來比較簡單,基本是每個Java工程師都能信手拈來的,本文將結合多執行緒、類的載入等知識,系統地介紹一下單例模式的演變,並體現在7種不同的單例設計中。說到這個,非常像孔乙己裡那個“回字有四種寫法”的梗,不過與封建迂腐

如何建立一個物件

為什麼需要單例模式 在應用程式中,經常會用到單例模式,即這個類只能存在一個物件例項。 那麼為什麼需要這種模式,我們在一個程式應用中,只需要建立一次性的物件例項以節省記憶體資源,避免重複建立的開銷,以便後面使用可以更快的訪問。 如何寫一個單例模式   單例作為所有設計模式中最簡單的設計模式之一,其建立是非

如何創建一個對象

最簡 初始化 修飾 就是 裏的 這一 tin 並且 資源 為什麽需要單例模式 在應用程序中,經常會用到單例模式,即這個類只能存在一個對象實例。 那麽為什麽需要這種模式,我們在一個程序應用中,只需要創建一次性的對象實例以節省內存資源,避免重復創建的開銷,以便後面使用可以更快的

設計模式學習筆記模式

單例模式(Singleton Pattern): Ensure a class has only one instance, and provide a global point of access to it. (確保某一個類只有一個例項,並向整個系統提供這個例項的

設計模式學習總結2模式、建造者模式、原型模式

單例模式(Singleton Pattern) 這種模式涉及到一個單一的類,該類負責建立自己的物件,同時確保只有單個物件被建立。這個類提供了一種訪問其唯一的物件的方式,可以直接訪問,不需要例項化該類的物件。 單例模式有以下三點注意: 1、單例類只能有一個例項。 2、單

JS設計模式--- 模式

我們繼續說小明那個例子 上次說到小明買回了所有的東西,書院的先生一看賬單:¥4386 雖然覺得這錢花的有點多,但這一次的採購還是要交給小明去做 先生說:小明啊,我給你一個賬單,你每買一件商品都要在這個

Java設計模式-模式模式

餓漢式單例類 餓漢式單例類在載入時單例物件已經被建立。程式碼如下: /** * 懶漢式單例 * @Author: Rick * @Date: 2018/10/31 17:44 */ public class EagerSingleton { pr

Java設計模式模式

目錄 1、單例模式簡介 1.1 應用例項 1.2 優勢和劣勢 1.3 使用場景 2、單例模式實現 2.1 餓漢式 2.2 懶漢式,執行緒不安全 2.3 懶漢式,執行緒安全 2.4 雙檢

控制反轉IOC的依賴注入方式 【調侃】IOC前世今生 IoC模式 談談對Spring IOC的理解 一個簡單的小程式演示Unity的三種依賴注入方式 小菜學習設計模式(—控制反轉Ioc IoC模式(依賴、依賴倒置、依賴注入、控制反轉 IoC模式

轉自:https://www.cnblogs.com/ysyn/p/5563256.html 引言:    專案中遇到關於IOC的一些內容,因為和正常的邏輯程式碼比較起來,IOC有點反常。因此本文記錄IOC的一些基礎知識,並附有相應的簡單例項,而在實際專案中再複雜的應用也只是在

設計模式學習——模式

閒話一二 清明小長假,由於沒有回老家探親,趁著難得的三天假期,可以好好地豐富下自己的知識儲備。今天是第一天,上午花了半天時間看了下單例模式,正好解決了最近手頭自動化測試工作中碰到的困擾,也順便了解了下volatile關鍵字的使用。 也許有人會說,網上關於設計模式的文章很多,為什麼還要寫設計模式。但是,那畢竟是

小菜學習設計模式—控制反轉Ioc

寫在前面 設計模式目錄: 本篇目錄:   好長時間沒有更新設計模式系列了,不是不想寫,奈何小菜功力有限,這段時間也在給自己充電,畢竟路要一步一步走,急不得。   控制反轉(Inversion of Control)是解決程式耦合問題的一種方案,還有種叫法是依賴注入(Dependency Inj

小菜學習設計模式—原型Prototype模式

1 /// <summary> 2 /// 心臟類 3 /// </summary> 4 public class Heart 5 { 6 private int _size; 7 p

小菜學習設計模式—工廠方法Factory Method模式

前言 設計模式目錄: 本篇目錄:   其實大家都知道,在工廠方法(Factory Method)模式之前有個簡單工廠模式,也就是靜態工廠方法(Static Factory Method)模式,在簡單工廠模式之前有個我們都熟悉的三層架構模式,那我們就上到下一層一層的來了解下。 三層架構   三

小菜學習設計模式—模板方法Template模式

1 /// <summary> 2 /// 資料庫操作類 3 /// </summary> 4 public class DbHelperOra 5 { 6 public static bool Quer

【原】從頭學習設計模式——模式

一、引入   單例模式作為23種設計模式中的最基礎的一種模式,在平時開發中應用也非常普遍。到底哪些類應該設計成單例的呢,我們來舉個最通俗的例子。在一個父容器中單擊某個選單項開啟一個子視窗,如果不使用單例又沒有作選單項的可用控制的話,每次單擊選單項都會開啟一個新視窗。這不僅會浪費記憶體資源,在程式邏輯

Java 多執行緒學習筆記十一 設計模式延遲載入/懶漢模式DCL解決執行緒安全問題

package extthread; import test.MyObject; public class MyThread extends Thread { @Override publi

設計模式模式的七種寫法

面試的時候,問到許多年輕的Android開發他所會的設計模式是什麼,基本上都會提到單例模式,但是對單例模式也是一知半解,在Android開發中我們經常會運用單例模式,所以我們還是要更瞭解單例模式才對。 定義:保證一個類僅有一個例項,並提供一個訪問它的全域性訪問