詳解Go語言設計模式之單例模式_第1頁
詳解Go語言設計模式之單例模式_第2頁
詳解Go語言設計模式之單例模式_第3頁
詳解Go語言設計模式之單例模式_第4頁
詳解Go語言設計模式之單例模式_第5頁
已閱讀5頁,還剩1頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第詳解Go語言設計模式之單例模式目錄單例模式的概念單例模式結(jié)構(gòu)單例模式的使用場景單例模式例子:特殊的計數(shù)器第一個單元測試單例模式實現(xiàn)單例模式優(yōu)缺點

單例模式的概念

單例模式很容易記住。就像名稱一樣,它只能提供對象的單一實例,保證一個類只有一個實例,并提供一個全局訪問該實例的方法。

在第一次調(diào)用該實例時被創(chuàng)建,然后在應用程序中需要使用該特定行為的所有部分之間重復使用。

單例模式結(jié)構(gòu)

單例模式的使用場景

你會在許多不同的情況下使用單例模式。比如:

當你想使用同一個數(shù)據(jù)庫連接來進行每次查詢時當你打開一個安全Shell(SSH)連接到一個服務器來做一些任務時。而不想為每個任務重新打開連接如果你需要限制對某些變量或空間的訪問,你可以使用一個單例作為作為這個變量的門(在Go中使用通道可以很好地實現(xiàn))如果你需要限制對某些空間的調(diào)用數(shù)量,你可以創(chuàng)建一個單例實例使得這種調(diào)用只在可接受的窗口中進行

單例模式還有跟多的用途,這里只是簡單的舉出一些。

單例模式例子:特殊的計數(shù)器

我們可以寫一個計數(shù)器,它的功能是用于保存它在程序執(zhí)行期間被調(diào)用的次數(shù)。這個計數(shù)器的需要滿足的幾個要求:

當之前沒有創(chuàng)建過計數(shù)器count時,將創(chuàng)建一個新的計數(shù)器count=0如果已經(jīng)創(chuàng)建了一個計數(shù)器,則返回此實例實際保存的count數(shù)如果我們調(diào)用方法AddOne一次,計數(shù)count必須增加1

在這個場景下,我們需要有3個測試來堅持我們的單元測試。

第一個單元測試

與Java或C++這種面向?qū)ο笳Z言中不同,Go實現(xiàn)單例模式?jīng)]有像靜態(tài)成員的東西(通過static修飾),但是可以通過包的范圍來提供一個類似的功能。

首先,我們要為單例對象編寫包的聲明:

packagesingleton

typeSingletonstruct{

countint

varinstance*Singleton

funcinit(){

instance=Singleton{}

funcGetInstance()*Singleton{

returnnil

func(s*Singleton)AddOne()int{

return0

然后,我們通過編寫測試代碼來驗證我們聲明的函數(shù):

packagesingleton

import(

"testing"

funcTestGetInstance(t*testing.T){

count:=GetInstance()

ifcount==nil{

t.Error("Anewconnectionobjectmusthavebeenmade")

expectedCounter:=count

currentCount:=count.AddOne()

ifcurrentCount!=1{

t.Errorf("Aftercallingforthefirsttimetocount,thecountmustbe1butitis%d\n",currentCount)

count2:=GetInstance()

ifcount2!=expectedCounter{

t.Error("Singletoninstancesmustbedifferent")

currentCount=count2.AddOne()

ifcurrentCount!=2{

t.Errorf("Aftercalling'AddOne'usingthesecondcounter,thecurrentcountmustbe2butwas%d\n",currentCount)

}

第一個測試是檢查是顯而易見,但在復雜的應用中,其重要性也不小。當我們要求獲得一個計數(shù)器的實例時,我們實際上需要得到一個結(jié)果。

我們把對象的創(chuàng)建委托給一個未知的包,而這個對象在創(chuàng)建或檢索對象時可能失敗。我們還將當前的計數(shù)器存儲在變量expectedCounter中,以便以后進行比較。即:

currentCount:=count.AddOne()

ifcurrentCount!=1{

t.Errorf("Aftercallingforthefirsttimetocount,thecountmustbe1butitis%d\n",currentCount)

}

運行上面的代碼:

$gotest-v-run=GetInstance.

===RUNTestGetInstance

singleton_test.go:12:Anewconnectionobjectmusthavebeenmade

singleton_test.go:19:Aftercallingforthefirsttimetocount,thecountmustbe1butitis0

singleton_test.go:31:Aftercalling'AddOne'usingthesecondcounter,thecurrentcountmustbe2butwas0

---FAIL:TestGetInstance(0.00s)

FAIL/yuzhoustayhungry/GoDesignPattern/singleton0.412s

單例模式實現(xiàn)

最后,我們必須實現(xiàn)單例模式。正如我們前面提到的,通常做法是寫一個靜態(tài)方法和實例來檢索單例模式實例。

在Go中,沒有static這個關(guān)鍵字,但是我們可以通過使用包的范圍來達到同樣的效果。

首先,我們創(chuàng)建一個結(jié)構(gòu)體,其中包含我們想要保證的對象在程序執(zhí)行過程中成為單例的對象。

packagesingleton

typeSingletonstruct{

countint

varinstance*Singleton

funcinit(){

instance=Singleton{}

funcGetInstance()*Singleton{

ifinstance==nil{

instance=new(Singleton)

returninstance

func(s*Singleton)AddOne()int{

s.count++

returns.count

}

我們來分析一下這段代碼的差別,在Java或C++語言中,變量實例會在程序開始時被初始化為NULL。但在Go中,你可以將結(jié)構(gòu)的指針初始化為nil,但不能將一個結(jié)構(gòu)初始化為nil(相當于其他語言的NULL)。

所以varinstance*singleton*這一語句定義了一個指向結(jié)構(gòu)的指針為nil,而變量稱為instance。

我們創(chuàng)建了一個GetInstance方法,檢查實例是否已經(jīng)被初始化(instance==nil),并在已經(jīng)分配的空間中創(chuàng)建一個實例instance=new(singleton)。

Addone()方法將獲取變量實例的計數(shù),并逐個加1,然后返回當前計數(shù)器的值。

再一次運行單元測試代碼:

$gotest-v-run=GetInstance.

===RUNTestGetInstance

---PASS:TestGetInstance(0.00s)

ok/yuzhoustayhungry/GoDesignPattern/singleton0.297s

單例模式優(yōu)缺點

優(yōu)點:

你可以保證一個類只有一個實例。你獲得了一個指向該實例的全局訪問節(jié)點。僅在首次請求單例對象時對其進行初始化。

缺點:

違反了單一職責原則。該模式同時解決了兩個問題。單例模式可能掩蓋不良設計,比如程序各組件之間相互了解過多等。該模式在多線程環(huán)境下需要進行特殊

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論