佐々木屋

技術的なことから趣味まで色々書きます

静的クラスとシングルトン

インスタンスを複数作成しないで、どのクラスからも同じインスタンスを見に行くといった場合は静的クラスを利用します。VB.NETの場合はモジュールがほぼ同じような役割(全く一緒ではない)です。

public static class StaticClass {
    public static string UserName { get; set; }
    public static string UserID { get; set; }
}
Public Module StaticClass
    Public Property UserName As String
    Public Property UserID As String
End Module



静的クラスの場合は継承が使用できないことや、インスタンスを特定場面で入れ替えたい場合に対応できない問題があります。そこでシングルトンが必要になります。

シングルトンはクラスのインスタンスが一つであることを保証する設計です。基本的には、外部ファイルのような特定リソースへの場所を一つにしたい場合や、固定値を定義する場合などに使用します。

シングルトン設計は以下の要領で行います。

  1. コンストラクタをprivateにしてインスタンス作成を禁止する
  2. インスタンスをプライベートな静的メンバ変数に保持する
  3. インスタンスの生成を静的コンストラクタまたは静的メンバ変数の初期化で行う
  4. インスタンスを公開する静的なメソッドかプロパティを追加する
public class SingletonClass : Class1 {
    private static SingletonClass obj = new SingletonClass();
        
    private SingletonClass() { }

    public static SingletonClass Instance {
        get {
            return obj;
        }
    }

    public string UserName { get; set; }
    public string UserID { get; set; }
}
Public Class SingletonClass
    Inherits Class1

    Private Shared obj As New SingletonClass()

    Private Sub New()
    End Sub

    Public Shared ReadOnly Property Instance() As SingletonClass
        Get
            Return obj
        End Get
    End Property

    Public Property UserName As String
    Public Property UserID As String
End Class

コンストラクタをprivateにすることで、クラス外からのインスタンス化を禁止しています。唯一のインスタンスはクラスが初めて使用される時にインスタンス保持メンバー変数宣言時に生成されます。インスタンスの受け渡しは静的プロパティを介して行われます。これは静的メソッドで実装しても構いません。

別の手法として、インスタンス生成を静的コンストラクタで行うことも可能です。インスタンスの受け渡しも静的メソッドで実現してみましょう。

public class SingletonClass : Class1 {
    private static SingletonClass obj;

    private SingletonClass() { }
    static SingletonClass() {
        obj = new SingletonClass();
    }

    public static SingletonClass Instance() {
        return obj;
    }

    public string UserName { get; set; }
    public string UserID { get; set; }
}
Public Class SingletonClass
    Inherits Class1

    Private Shared obj As SingletonClass

    Private Sub New()
    End Sub
    Shared Sub New()
        obj = New SingletonClass()
    End Sub

    Public Shared Function Instance() As SingletonClass
        Return obj
    End Function

    Public Property UserName As String
    Public Property UserID As String
End Class



なお、C#VB.NET)は.NET Frameworkによって静的な初期化が確実に実行されますので、JavaC++のような動的な初期化を行う必要はありません。なお、シングルトンはスレッドセーフです。

また、.NET Framework上では、シングルトンのインスタンス破棄はアプリケーション終了時に自動的に行われます。破棄すべきリソースを保持しており、明示的な破棄が必要な場合は、通常クラス同様にIDisposableインターフェースを実装すれば良いことになります。