こんにちは。KOUKIです。
以前、シングルトンパターンについて記事を書きましたが、別パターンでも実装したので紹介します。
<目次>
そもそもシングルトンパターンとは?
シングルトンパターンは、アプリケーション内で「シングルインスタンスを提供することを保証する」デザインパターンです。
インスタンスが重複して生成されないことを保証することに、どのようなメリットがあるのでしょうか?
パッと思いつく限り、以下のシチュエーション時に便利です。
- データベースにアクセスするコネクションインスタンスを作成したい
- サーバーにSSH接続する際のインスタンスを作成したい
- 変数や何らかの空間に対して、アクセス制限を設けたい
しかも、シングルトンパターンはそれほど難しくないので、サクッと覚えてしまいましょう。
実装
早速、実装に入ります。
作るものは、カウンターアプリケーションです。

カウンターのシングルインスタンスを用意し、全ての処理をそのシングルインスタンスに記録していくイメージです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package singleton type singleton struct { count int } var instance *singleton func GetInstance() *singleton { if instance == nil { instance = new(singleton) } return instance } func (s *singleton) AddOne() int { s.count++ return s.count } func (s *singleton) RemoveOne() int { s.count-- return s.count } |
GetInstanceでシングルインスタンスを取得します。instance変数はグローバル変数になっており、GetInstanceを呼ぶと空チェックを行い、空の場合はインスタンス生成、空でない場合はinstance変数を返します。
AddOneやRemoveOneはシングルインスタンスが保証されているかチェックするためのメソッドです。
テスト
テストコードを実装し、シングルトンパターンの検証を行いましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
package singleton import "testing" func TestGetInstance(t *testing.T) { // インスタンス取得 counter1 := GetInstance() if counter1 == nil { t.Error( "expected pointer to Singleton after calling GetInstance(). not nil") } expectedCounter := counter1 currentCount := counter1.AddOne() if currentCount != 1 { t.Errorf( "After calling for the first time to count, the count must be 1 but it is %d\n", currentCount, ) } // インスタンス取得 counter2 := GetInstance() if counter2 != expectedCounter { t.Error( "Expected same instance in counter2 but it got a different instance") } // インスタンス取得 counter3 := GetInstance() currentCount = counter3.RemoveOne() if currentCount != 0 { t.Errorf( "After calling for the third time to count, the count must be 0 but it is %d\n", currentCount, ) } } |
インスタンスを3回取得して、それぞれが持つ値をテストしています。
下記のコマンドで、テストしてみましょう。
1 2 3 |
$ go test PASS ok github.com/hoge/go-algorithms/design-pattern/singleton 1.228s |
OKですね!
おわりに
シングルトンパターンは、幾多にも及ぶデザインパターンの中でも特に有名で、実務でも使用する頻度が高いパターンです。
しかし、この記事で見たように「簡単に覚えられるパターン」でもあるので、積極的に取り入れてみましょう。
それでは、また!
Go記事まとめ
ソースコード
singleton.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package singleton type singleton struct { count int } var instance *singleton func GetInstance() *singleton { if instance == nil { instance = new(singleton) } return instance } func (s *singleton) AddOne() int { s.count++ return s.count } func (s *singleton) RemoveOne() int { s.count-- return s.count } |
singleton_test.go
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
package singleton import "testing" func TestGetInstance(t *testing.T) { // インスタンス取得 counter1 := GetInstance() if counter1 == nil { t.Error( "expected pointer to Singleton after calling GetInstance(). not nil") } expectedCounter := counter1 currentCount := counter1.AddOne() if currentCount != 1 { t.Errorf( "After calling for the first time to count, the count must be 1 but it is %d\n", currentCount, ) } // インスタンス取得 counter2 := GetInstance() if counter2 != expectedCounter { t.Error( "Expected same instance in counter2 but it got a different instance") } // インスタンス取得 counter3 := GetInstance() currentCount = counter3.RemoveOne() if currentCount != 0 { t.Errorf( "After calling for the third time to count, the count must be 0 but it is %d\n", currentCount, ) } } |
コメントを残す
コメントを投稿するにはログインしてください。