Singletonパターンの「だらしない」実装

Singletonパターンに限らず、「初回アクセス時に初期化するプロパティ」などは比較的よく実装しますよね。
これを在り来りな方法で書けば、およそ以下のようになることと思います。


type Singleton private () =
do printfn "生成されました"

static let mutable instance = None

static member Instance =
match instance with
| Some x -> x
| None -> let x = Singleton() in instance <- Some x ; x

> Singleton.Instance ;;
生成されました
val it : Singleton = FSI_0007+Singleton
> Singleton.Instance ;;
val it : Singleton = FSI_0007+Singleton
これで、実際にアクセスされるまでインスタンス化を遅らせることができました。


今行っていたことは正しく遅延評価です。
然すれば、lazyを使って以下のようにだらしなく書くこともできます。


type LazySingleton private () =
do printfn "生成されました!"

static let instance = lazy LazySingleton()
static member Instance = instance.Force()

> LazySingleton.Instance ;;
生成されました!
val it : LazySingleton = FSI_0007+LazySingleton
> LazySingleton.Instance ;;
val it : LazySingleton = FSI_0007+LazySingleton

結果はLazyクラスの内部にキャッシュされているため、複数回評価をしてもインスタンスは無二のものとなります。シンプル!