設計模式系列 單例模式

2022-02-27 13:42:36 字數 2599 閱讀 9133

今天單位有自己的食堂啦,發郵件收了工卡之後統一拿去啟用,以後就用工卡去食堂吃飯啦,早上2元,中午10元,晚上3元,都是自助噢,很爽,不過還是有一推人沒有第一時間啟用卡,也有的人啟用卡了忘記自己啟用了,我就是其中乙個,無奈下我只好到食堂自己去啟用卡了,餐廳只有乙個機會卡的櫃檯所以啟用的時候需要排隊,還好我來的早,提前搞定,剛出門時就看又一批啟用工卡的人來啦。

下班後。不例外繼續到食堂吃飯,便宜嘛自然人也就不少,當然也包括啟用工卡的人,吃飯是心裡就暗自想,這不就是設計模式裡面的一種場景嗎? 乙個餐廳只有乙個啟用卡的櫃檯。在餐廳的作用域內提供了乙個全域性的訪問點。

1.模擬該場景:

首先分析乙個這個場景,首先:

① 我們需要乙個餐廳類(restaurant)。

② 接下來我們還要設計乙個櫃檯類(counter),餐廳包含櫃檯,並且只能擁有乙個櫃檯。

③ 櫃檯類中包含乙個用來啟用工卡(activationcard)的功能,好讓員工可以在餐廳用餐。

廢話不多說模擬場景**如下:

//餐廳類

public

class restaurant

//櫃檯類

public

class counter

}static

void main(string args)

這時,似乎不出來**中有什麼問題,但是仔細想想,如果這個時候我在呼叫啟用工卡的時候將獲取到的櫃檯物件重新例項化一次呢?彷彿憑空多製造出了乙個櫃檯的感覺一樣,為了確保我們在同乙個範圍內只有乙個櫃檯例項我們可以考慮單例模式。

2.引入單例模式

那麼如何讓同乙個範圍內的物件僅有乙個例項呢?

我們可以類的定義中做手腳,改裝後的櫃檯類如下:

//櫃檯類

public

class counter

public

static counter getcounterinstance()

return instance;}//

啟用工卡方法

public

void activationcard()

}那麼櫃檯是屬於餐廳的,必然要給餐廳中安裝櫃檯,平且讓餐廳提供啟用工卡的服務。餐廳類**如下:

//餐廳類

public

class restaurant

}主函式呼叫**如下:

static

void main(string args)

這時乙個最基本的單例模式就體現出來了,前面介紹過,單例模式:就是保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點。

現在看來上面的**確實做到了這一點,但是在多執行緒情況下會怎樣呢?我們來看獲得餐廳例項的方法,這個方法裡面實現了僅建立乙個例項的邏輯,**如下:

public

static counter getcounterinstance()

return instance;

}如果這是兩個執行緒同時訪問,那麼就會造成同時建立了兩個例項,因為兩個執行緒到達這段**時,該例項都是未建立的,那麼如何解決這個問題呢?在例項化方法中加入乙個臨界區是乙個很好的解決辦法,這樣就能保證乙個執行緒進去臨界區時,另乙個執行緒在臨界區外面等待,**如下:

private

static

readonly

object obj = typeof(object);

public

static counter getcounterinstance()

}return instance;

}這個時候就解決了執行緒同步的問題了,在多執行緒環境下也會只有乙個例項被建立,成為了真真正正的單例模式!

那麼在考慮乙個問題,回到我們之前的啟用工卡場景中,排隊的人中有很多卡已經啟用自己卻不知道的,也就是說,當很多執行緒執行建立例項的**時,例項已經是建立過的,那麼不必要例項化的執行緒我們能不能就不讓它們進入臨界區,減少系統的效能開銷?

**如下:

private

static

readonly

object obj = typeof(object);

public

static counter getcounterinstance()}}

return instance;

}這下就是我們傳說中的單例模式了,並且對效能也進行了優化。

3.c#版的單例模式

那麼根據c#的語言特性,實現單例模式又是什麼樣子呢?

①我們可以吧getcounterinstance()方法 替換成 c#的屬性。

②我們可以使用密封類,阻止型別的派生,避免多例項化物件。

③使用靜態並且唯讀的私有字段存放型別的唯一例項

**如下:

//櫃檯類

public

sealed

class counter

//返回型別例項屬性

public

static counter instance}//

啟用工卡方法

public

void activationcard()

}暈。當我想完時,晚飯已經涼了。算了,這不就是程式設計師的生活嘛?

設計模式系列 單例模式

單例模式 確保乙個類只有乙個例項,並提供乙個全域性訪問點。什麼情況下需要單例模式?一些類提供公共功能供別人呼叫,本身不會處理業務邏輯 類會被許多類和執行緒呼叫 單例模式的一些注意點 單例的生存期超長,會導致記憶體的持續占用。單例在多執行緒環境需要小心的處理執行緒互斥,進行資源保護。單例在類的繼承樹中...

設計模式系列 單例模式

單例模式就是指單例類在一定的生命週期內只能有乙個物件例項,單例類的建立必須是本身,並能給使用者提供自身。在現實世界中,每個生命體都可以被看做是乙個單例物件,唯一且具體,具有不可複製性。同樣的,在軟體開發領域中,有時我們需要保證客戶端在當前的客戶機上只能執行乙個例項這個時候,我們就應該考慮使用單例模式...

設計模式系列之單例模式

在設計模式中,單例模式是屬於比較簡單是卻很實用的一種設計模式,單例模式的含義就是乙個類在程式中只能有不多於1個物件。但是看似簡單的單例模式,一不小心就會出現一些難以發現的隱藏bug。問題一 系統擁有多個類載入器 當系統擁有多個類載入器的時候,而又同時使用單例模式,解決辦法就是 為單例的類和單例類指定...