デザインパターン第14回「Singletonパターン」その2
以前書いた、デザインパターン第7回「Singletonパターン」その1はこちらです。
結城先生のホームページに、Singletonのサブクラス化という記事がある。
Singletonの考え方にもいろいろあるけれど、その中の考え方のひとつ、
「(2) クラスごとに管理 ―― クラスごとに唯一のインスタンスを作る」ってやつが個人的に有用だと思った。
コンバット越前の如く、「せっかくなので俺はC#を選ぶゼ。」というわけでC#でジェネリックで書いてみた。
以下、クラスごとに唯一のインスタンスを作る抽象Singletonクラス
using System; using System.Collections.Generic; using System.Text; namespace ClassLibrary1 { /// <summary> /// 抽象Singletonクラス /// </summary> public abstract class AbstractSingletonClass : MarshalByRefObject { #region メンバ /// <summary> /// 唯一のインスタンスを保持するためのHashtable /// </summary> private static Dictionary<Type, AbstractSingletonClass> dicSingletonInstance = new Dictionary<Type, AbstractSingletonClass>(); /// <summary> /// lockオブジェクト /// </summary> private static readonly object lockObject = new object(); #endregion #region コンストラクタ /// <summary> /// コンストラクタ /// サブクラスのコンストラクタのアクセシビリティはprotectedに設定してください。 /// </summary> protected AbstractSingletonClass() { if (dicSingletonInstance.ContainsKey(this.GetType())) { throw new System.InvalidOperationException("インスタンスは既に生成されています。\r\nAbstractSingletonClassのサブクラスのコンストラクタのアクセシビリティは\r\nprotectedにしてください。"); } //Dictionaryに型ごとの唯一のインスタンスを保持 dicSingletonInstance.Add(this.GetType(), this); } #endregion #region メソッド /// <summary> /// 指定の型のSingletonインスタンスを取得します。 /// </summary> /// <typeparam name="T"> /// 指定の型 T :制約 AbstractSingletonClassのサブクラス /// </typeparam> /// <returns>指定の型のSingletonインスタンス</returns> public static T GetInstance<T>() where T : AbstractSingletonClass { lock (lockObject){ // まだ作成されていない場合、インスタンスを生成 if (!dicSingletonInstance.ContainsKey(typeof(T))) { // 指定された型のインスタンスを生成 System.Activator.CreateInstance(typeof(T), true); } return (T)dicSingletonInstance[typeof(T)]; } } #endregion } }
ある程度の規模のシステムでは、Singletonにしたいクラスってのが結構な数でてくるので、
いちいちクラスごとに実装するのが面倒と感じることもある。そんなとき、このスーパークラスAbstractSingletonClassを継承すれば、
サブクラスは漏れなくSingletonなクラスとなってしまうとゆー。ゴリゴリ実装があるような重いクラスには適用しにくいけど、
実装の少なめな軽いSingletonなクラスが必要となるケースを考えた場合、これは、ちょっと便利かもしれない。