ようこそ。睡眠不足なプログラマのチラ裏です。

デザインパターン第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なクラスが必要となるケースを考えた場合、これは、ちょっと便利かもしれない。