はじめに
ZOOM勉強会の議事録です。 「増補改訂版Java言語で学ぶデザインパターン入門」を読んで、プログラム作成・パターンの理解を行います。 第5回はSingletonです。Singleton
インスタンスが1つしか無いことを保証するパターンです。 Singletonクラスの役割は以下です。- Singleton 唯一のインスタンスを提供するクラス
また、コードは以下です。
Singleton
Public Class Singleton
'唯一のインスタンス
Private Shared singleton = New Singleton()
'外部からはインスタンス化できない
Private Sub New()
End Sub
'唯一のインスタンスを返す
Public Shared Function GetInstance() As Singleton
Return singleton
End Function
End Class
Singletonパターンでは、以下の手順で唯一のインスタンスを保証しています。
- コンストラクタをPrivateにし、外部からはインスタンス生成できない
- フィールドに唯一のインスタンスを用意し、クラスのロード時にのみインスタンス化する
メリット
- インスタンスが1つであることが保証される
- 1クラス内で完結しているパターンのため導入が簡単
デメリット
- 多くの場所からSingletonクラスを使用している場合、Singletonクラスの変更が多くの場所に影響を及ぼす
- Singletonの派生クラスはSingletonでなくなるため、Singletonにしたい場合は再度実装する必要がある
- 使う側はこのクラスがSingletonであり、独自に定義されたメソッドでインスタンスを取得すると知っていなければならない
議論
調べたところSingletonは、デザインパターンの中でも不評なようです。 その理由として、Singletonは実質グローバル変数であるというような理由が見受けられました。Singletonを活用する方法の議論
あまりSingletonは使わない方がいいのではという話しになる一方で、状態を持たない定数のような形であればいいのではという意見が出ました。 例えばマルバツゲームのマスの状態を表す「◯・✕・空」などの状態そのものをクラスで表現する場合です。 以下のような形です。Maru
Public Class Maru : Implements ISquare
Private Shared ReadOnly maru = New Maru()
Private Sub New()
End Sub
Public Shared Function GetInstance() As ISquare
Return maru
End Function
Public Function GetSquareImage() As Image Implements ISquare.GetSquareImage
Return My.Resources.Maru
End Function
End Class
このようにすることで、盤上にある同一の状態を1つのインスタンスのみで表現できます。
するとメモリの使用量が節約できるという意見でした。
Singletonに代わる方法
Singletonがだめなら他の方法が無いか調べ、アジャイルソフトウェア開発の奥義 第2版でMonostateパターンというものを見つけました。Monostate
インスタンス自体を一つにするのでなく、インスタンスの振る舞いを1つにします。 振る舞いを1つにすることで別々のインスタンスがあたかも1つのインスタンスかのように振る舞います。Monostate
Public Class Monostate
Private Shared itsX As Integer = 0
Public Sub New()
End Sub
Public Sub SetX(ByVal x As Integer)
itsX = x
End Sub
Public Function GetX() As Integer
Return itsX
End Function
End Class
以上のようにすべてのフィールド変数をShared(javaだとstatic)にし、すべてのインスタンスが、共有するフィールド変数にアクセスすることによって同じ振る舞いを実現しています。
メリット
- 通常のクラスのようにインスタンス化して使える
- 派生クラスにフィールドを共有させることができる
- 静的メソッドを強制されないため、メソッドをオーバーライドして異なる振る舞いを提供できる
デメリット
- Singletonよりインスタンスの生成・削除の機会が多い
以上のようにSingletonが構造で唯一のインスタンスを保証している一方で、Monostateは振る舞いで唯一性を保証しています。