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.
我希望你喜歡,這篇文章,期待你的評論和建議。
文章列表