原文鏈接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ Design Patterns Simplified - Part 2 (Singleton)【設計模式 ...
原文鏈接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/
Design Patterns Simplified - Part 2 (Singleton)【設計模式簡述--第二部分(單例模式)】
I am here to continue the explanation of Design Patterns. Today we will explain the easiest yet an important design pattern called Singleton.
這裡我繼續來解釋設計模式。今天我將會來解釋,最簡單但非常重要的設計模式,也就是單例模式。
In case you have not had a look at our first article, go through the following link:
這裡假設,你還沒有看我的第一篇文章,請先回去閱讀吧,下麵是鏈接:
Before talking about its implementation let’s begin with some fundamental questions as in the following.
來討論單例模式是如何實現之前,我們先看看下麵一些基礎的問題吧。
Use of the Singleton Pattern【使用單例模式】
As the name suggests, the Singleton Pattern allows only one instance of a class to be created.
就像這個名字一樣,單例模式只允許,創建一個類的實例。
When do we need to have only one instance of a class?
為什麼我們只需要一個類的實例?
There are many possible requiremetns for a instance of a class but they all tend to have the one objective that we don’t want to change the state of the object or we want to keep the class stateless.
這裡有許多可能的requiremetns類的實例,但是它們都想要只有一個對象,所以我們不能去改變對象的狀態或者使對象的狀態變成無效的。
A simple example could be that you want to load some master data at once and let the consumers of the data make a call to the Singleton class instead of each consumer making various calls by creating a new instance.
舉一個簡單的例子,你想要立刻載入主表的數據,並且讓一個單例類來調用獲取客戶表的數據,而不是對於每一個客戶,都來創建一個類的實例來調用獲取數據。
In general, in any complex enterprise application, Repository and Data Access Layer classes can be seen as a Singleton since typically we don’t want them to maintain the state in these layers.
一般來說,在任何複雜點的企業級應用程式中,倉儲和數據訪問層的類,可以作為單例來看待,因為我們不想要它們在這些層中,保持狀態。
Some other example could be cross-cutting concerns like Logging, Configuration, Caching and so forth that can also be implemented as a Singleton since we want a single and global point of access to these classes.
其他的例子就是橫切關註點了,例如日誌,系統配置,緩存等等,可以同樣設計為單例,因為我們想要對這些類,進行全局的,單一的訪問。
Apart from the core consideration explained above, I have seen that developers, mostly not so experienced sometimes, create unnecessarily instances that creates not just an overhead to memory but also impacts the overall performance of an application.
除了上面解釋的,我看到過很多的開發者,有時候並不是那麼有經驗,他們創建不必要的實例,這不僅僅增加了記憶體的開銷,同樣也影響了系統的性能。
Why not Static classes【為什麼不使用靜態類】
There can be several reasons why to not use a static class however I can think of a few as follows.
至於為什麼不使用靜態類,我認為有如下的原因:
- There can be cases where you want to implement interfaces (maybe to implement IOC, I will explain IOC later) in a class that can be done in a Singleton implementation but not in the static one.
可能存在這樣的情況:你想要在類中實現某個介面【可能是實現IOC,我後面會降到IOC】,這種情況可以在單例中做到,但是不能在靜態類實現。 - If required, you can use a singleton class as a method parameter whereas you cannot do that with a static class.
Special care for Singleton classes【特別要說的就是單例類】
We need to take special care for Singleton classes. The idea of a state of a class comes with some extra care that means we need to handle synchronization issues in multi-threaded environments.
我們需要特別說到單例類,類的狀態,有一些需要註意點,也就是我們需要在多線程的環境中處理同步的問題。
Enough theory, now let’s talk about implementation.
好了,理論已經足夠了,現在我們來討論怎麼實現單例模式吧。
Let’s have a look at the most basic implementation.
我們先看看最基本的實現。
In the first example below, we have implemented a Singleton with Lazy loading since the instance will not be created until the caller calls the GetInstance method for the first time.
在下麵的例子中,我實現了一個懶載入的單例,因為這個實例只有在GetInstance方法第一次被調用的時候,才會創建類的實例。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
/// <summary>
/// SingletonClass單例模式學習
/// </summary>
public class SingletonClass
{
/// <summary>
/// 創建私有的,靜態的,類的變數
/// </summary>
private static SingletonClass instance = null;
/// <summary>
/// 創建私有的SingletonClass無參構造函數
/// </summary>
private SingletonClass()
{
}
/// <summary>
/// 創建靜態的屬性GetInstance
/// </summary>
public static SingletonClass GetInstance
{
get
{
if (instance == null)
{
//實例化SingletonClass
instance = new SingletonClass();
}
return instance;
}
}
}
}
Let’s try to fix the sync issue that may arise in multi-threaded environments. For this, we will use a double-lock mechanism.
現在我們來修複,上面例子中在多線程環境中,可能出現的同步問題吧。對於這個,我將會使用一個雙鎖機制。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
/// <summary>
/// SingletonClass單例模式學習
/// </summary>
public class SingletonClass
{
/// <summary>
/// 創建私有的,靜態的,類的變數
/// </summary>
private static SingletonClass instance = null;
private static object lockMe = new object();
/// <summary>
/// 創建私有的SingletonClass無參構造函數
/// </summary>
private SingletonClass()
{
}
/// <summary>
/// 創建靜態的屬性GetInstance
/// </summary>
public static SingletonClass GetInstance
{
get
{
if (instance == null)
{
lock (lockMe)
{
if (instance == null)
{
//實例化SingletonClass
instance = new SingletonClass();
}
}
}
return instance;
}
}
}
}
And in the last, Singleton with static initializations. Please note that the .NET Framework guarantees thread safety for static initialization so we don’t need extra care for sync issues however we may not get the benefit of lazy loading of objects here.
最後,我們看下單例模式靜態的初始化。請註意對於靜態的初始化,.NET Framework保證了線程安全,我們不必要去關心同步的問題,但是這種情況下,我們不能從懶載入對象中獲益。
public class SingletonClass
{
private static SingletonClass instance = new SingletonClass();
private SingletonClass() {}
public static SingletonClass GetInstance
{
get
{
return instance;
}
}
}
I hope you have liked this article. I look forward to your comments/suggestions.
我希望你喜歡,這篇文章,期待你的評論和建議。