GoFのデザインパターンを学習する素材として、書籍「増補改訂版Java言語で学ぶデザインパターン入門」が参考になるみたいですね。
取り上げられている実例は、JAVAベースのため、Pythonで同等のプラクティスに挑んだことがありました。
Qiita記事: "Pythonで、デザインパターン「Singleton」を学ぶ"
今回は、Pythonで実装した”Singleton”のサンプルアプリをGolangで実装し直してみました。
■ Singleton(シングルトン)
Singletonパターン(シングルトン・パターン)とは、オブジェクト指向のコンピュータプログラムにおける、デザインパターンの1つである。GoF (Gang of Four; 4人のギャングたち) によって定義された。Singleton パターンとは、そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのことである。ロケールやルック・アンド・フィールなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される
(以上、ウィキペディア(Wikipedia)より引用)
■ "Singleton"のサンプルプログラム
■ サンプルプログラムの詳細
Gitリポジトリにも、同様のコードをアップしています。
https://github.com/ttsubo/study_of_design_pattern_with_golang/tree/master/Singleton
- ディレクトリ構成
.
├── step1
│ └── Main.go
└── step2
└── Main.go
インスタンスが一つしか作成できないようなクラスを定義してみます。
package main
import "fmt"
// Singleton is struct
type Singleton struct {
}
// MyClass is struct
type MyClass struct {
Singleton
input int
}
var instance *MyClass
func getInstance(input int) *MyClass {
if instance == nil {
instance = &MyClass{input: input}
} else {
instance.input = input
}
return instance
}
func main() {
one := getInstance(1)
fmt.Printf("one.input=%d\n", one.input)
two := getInstance(2)
fmt.Printf("one.input=%d, twe.input=%d\n", one.input, two.input)
one.input = 0
fmt.Printf("one.input=%d, twe.input=%d\n", one.input, two.input)
}
動かしてみる
$ go run step1/Main.go
one.input=1
one.input=2, twe.input=2
one.input=0, twe.input=0
なるほど、まるでグローバル変数のように振る舞いますねぇー
あと、こちらのWeb記事"Go 言語における Singleton Pattern"を参考に、少し、実装を修正してみます。
package main
import "fmt"
// Singleton is struct
type Singleton struct {
input int
}
func (s *Singleton) getInstance(input int) *Singleton {
s.input = input
return s
}
// MyClass is struct
type MyClass struct {
Singleton
}
var myclass = &MyClass{}
func main() {
one := myclass.getInstance(1)
fmt.Printf("one.input=%d\n", one.input)
two := myclass.getInstance(2)
fmt.Printf("one.input=%d, twe.input=%d\n", one.input, two.input)
one.input = 0
fmt.Printf("one.input=%d, twe.input=%d\n", one.input, two.input)
}
動かしてみる
$ go run step2/Main.go
one.input=1
one.input=2, twe.input=2
one.input=0, twe.input=0
同じ結果になりました
個人的に、こちらの書き方の方が、しっくりくる感じです