最終更新:2020/05/18
この記事の内容は
を参考にしてGo言語に置き換えた内容になってます。
わかりにくい箇所は私の責任であり、java言語で学ぶデザインパターンのせいではありません。
目次
- Singletonパターンとは
- Singletonパターンの構成
- サンプルコード
- サンプルコードの説明
- サンプルコードの実行
- 設計のヒント
- 関連しているパターン
1. Singletonパターンとは
Singletonパターンは、指定したインスタンスが絶対に1個しかないことを保障します。
2. Singletonパターンの構成
Singleton
Singletonは唯一のインスタンスを得るための関数をもちます。
このメソッドはいつも同じインスタンスを返します。
3. サンプルコード
package singleton
import (
"fmt"
"reflect"
"sync"
)
type Singleton struct {
// Some fields
}
var singleton *Singleton
var once sync.Once
func GetInstance() *Singleton {
once.Do(func() {
// 初期化
singleton = &Singleton{}
fmt.Println("インスタンスを生成しました。")
})
return singleton
}
// Client
func Client() {
obj1 := GetInstance()
obj2 := GetInstance()
if reflect.DeepEqual(obj1, obj2) {
fmt.Println("obj1とobj2は同じインスタンスです。")
} else {
fmt.Println("obj1とobj2は同じインスタンスではありません。")
}
}
4. サンプルコードの説明
上記のサンプルコードの構成は以下の通りです。
Singleton
Singletonの役割は、いつも同じインスタンスを返すことです。
メソッドでいつも同じインスタンスを返すようにします。
サンプルコードだとGetInstance関数が担います。
func GetInstance() *Single {
once.Do(func() {
// 初期化
singleton = &Single{}
fmt.Println("インスタンスを生成しました。")
})
return sharedInstance
}
once.Do
once.Doは、Onceのインスタンスに対して初めてDoが呼び出される場合にのみ、関数fを呼び出します。
なので上記のコードでは、最初のDoで
// 初期化
singleton = &Single{}
fmt.Println("インスタンスを生成しました。")
が実行されます。
reflect.DeepEqual
reflect.DeepEqualは、structの比較に使います。
アドレスは別で良くて、単純に指しているものが同じ内容か確認します。
5. サンプルコードの実行
サンプルコードをmain関数で呼び出します。
package main
import (
"github.com/java-lang-programming/marsa/singleton"
)
func main() {
singleton.Client()
}
実行すると以下が出力されます。
# go run main.go
インスタンスを生成しました。
obj1とobj2は同じインスタンスです。
6. 設計のヒント
なぜ制限を設ける必要があるのか
インスタンスが一つしかないという保証があれば、その前提条件の下でプログラミングができる
7. 関連しているパターン
以下のパターンでよく使います。
- Abstract Factoryパターン
- Builderパターン
- Facadeパターン
- Prototpeパターン