とはいえ、今回のお話はどちらかというと Java や C++ の学習によるシナジー効果で身に付けた知識だったりします。『VB しか必要ないから VB だけがんばる』という硬直した方針では、なかなか前に進めないものだなぁと思ったり思わなかったり。
そんなわけで本日は、GoF のデザインパターンの中から個人的に気に入っているものを独断と偏見でチョイスして、実際のソースコードとともにご紹介したいと思います。
【Singleton パターン】
まずは、理解しやすく実装も容易な Singleton パターンからご紹介しましょう。
これは、プログラム内に存在するオブジェクトが 1 つだけである事を保証するための仕組みです。一体それが何の役に立つのでしょうか。その答えの一つが『ゲームプログラマになる前に覚えておきたい技術』の p.183 で述べられていますので、当該箇所を引用します。
シングルトンクラスの目的は以下のようにまとめられる。……だそうです。
要するに、安全性を高めたグローバル変数のことである。
- 1. グローバル変数の危険さを軽減する
- 2. グローバル変数と同じように使えるようにする
実際には、オブジェクトを生成する際に New が実行されるたび、(新たなオブジェクトを格納するための)メモリ領域が逐一確保されます。そのため、このままでは『オブジェクトが 1 つである事』を保証できません。
Singleton クラスでは、コンストラクタを Private にする事によって、外側から New の実行を禁止します。Singleton クラスは、内部的に静的な唯一の自己参照 _instance を持ち、外部から Singleton オブジェクトを要求された場合は、その _instance を返却します。
以下に実装例を示します(展開してご覧ください)。
' ======================================== ' Singleton ' ======================================== ' ----------------------------------------- ' Singletonクラス Public Class Singleton Private Shared _instance As Singleton = New Singleton() ' インスタンス取得 Public Shared ReadOnly Property Instance() As Singleton Get Return _instance End Get End Property Private Sub New() Console.WriteLine("オブジェクトを生成しました") End Sub End Class ' ----------------------------------------- ' テスト用モジュール Module Module1 Sub main() ' Singleton であるオブジェクトの取得 Dim singleton1 = Singleton.Instance Dim singleton2 = Singleton.Instance If singleton1 Is singleton2 Then Console.WriteLine("同じオブジェクトです") Else Console.WriteLine("異なるオブジェクトです") End If End Sub End Module
実行すると、コンストラクタが 1 回しか実行されていない事、および main 内の singleton1 と singleton2 が同じオブジェクトを共有している事が分かります。
Singleton クラスがデータを適切にカプセル化していれば、前述の通り安全なグローバル変数として使用する事ができますし、また、New が重たいオブジェクトを使い回す際にも効果的でしょう。