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

下載本文檔

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

文檔簡(jiǎn)介

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

單例模式的概念

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

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

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

單例模式的使用場(chǎng)景

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

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

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

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

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

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

在這個(gè)場(chǎng)景下,我們需要有3個(gè)測(cè)試來(lái)堅(jiān)持我們的單元測(cè)試。

第一個(gè)單元測(cè)試

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

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

packagesingleton

typeSingletonstruct{

countint

varinstance*Singleton

funcinit(){

instance=Singleton{}

funcGetInstance()*Singleton{

returnnil

func(s*Singleton)AddOne()int{

return0

然后,我們通過(guò)編寫測(cè)試代碼來(lái)驗(yàn)證我們聲明的函數(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)

}

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

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

currentCount:=count.AddOne()

ifcurrentCount!=1{

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

}

運(yùn)行上面的代碼:

$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

單例模式實(shí)現(xiàn)

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

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

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

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

}

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

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

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

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

再一次運(yùn)行單元測(cè)試代碼:

$gotest-v-run=GetInstance.

===RUNTestGetInstance

---PASS:TestGetInstance(0.00s)

ok/yuzhoustayhungry/GoDesignPattern/singleton0.297s

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

優(yōu)點(diǎn):

你可以保證一個(gè)類只有一個(gè)實(shí)例。你獲得了一個(gè)指向該實(shí)例的全局訪問節(jié)點(diǎn)。僅在首次請(qǐng)求單例對(duì)象時(shí)對(duì)其進(jìn)行初始化。

缺點(diǎn):

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論