一回しか実行されないファクトリメソッド
DIで注入とかしないけど、とりあえずサービスクラスとかをプロパティ経由で取得したりするようにする場合が多い。けど、そんな時はDIでいうとこのシングルトンでよくて、同じオブジェクトでいい方が圧倒的に多い。
そんな時どうしてたかった言うと
private SampleService service; private SampleService Service { get { return service = service ?? new SampleService(); } }
みたいな。ちなみにマルチスレッドとか考えなくていい前提で。
まあnullだったら作って、あれば再利用ってことで全然機能はする。ライフサイクルも短い場合がほとんどなので弱参照とかも使う必要ないし、今まではこれで満足してた。
が、F#とかScalaを触るようになってこの書き方があまりにださい事に気づく。。
何がって、プライベート変数が心から邪魔。使わないくせにいるし。
でどうした
こうした。
class Program { static void Main(string[] args) { var test1 = Test.NewInstance(); Debug.Assert(test1.Val.Equals("1")); var test2 = Test.NewInstance(); Debug.Assert(test1.Val.Equals("2")); Debug.Assert(test1 == test2); } } public delegate T FactoryMethod<T>(); public class Test { public static FactoryMethod<Test> NewInstance; static Test() { NewInstance = delegate(){ var instatnce = new Test() { Val = "1" }; NewInstance = delegate() { instatnce.Val = "2"; return instatnce; }; return instatnce; }; } public string Val { get; private set; } }
一応参照の等価性とかも判断したり、値がちゃんと変わってるか見るために余計なコードも入ってるけどこんな感じ。
まあ、引数付きで初期化したい場合はFactoryMethodデリゲートをいろいろ作って対応すればいいとして、なかなかいいんじゃないかなと思うのはきっと僕だけだろう。だから会社では使わない。。。
ちなみにC#3.0以降ではちなみにC#3.0(.NET Framework4未満)では
会社がまだ2.0なのでついついdelegate使ったけど3.0風に書くとこんな感じ?
public class Test { public static Func<Test> NewInstance; static Test() { NewInstance = () => { var instatnce = new Test() { Val = "1" }; NewInstance = () => instatnce; return instatnce; }; } public string Val { get; private set; } }一応動いたから合ってると思う。てゆうか3.0からはラムダ式に加えてFuncデリゲートもあるからより簡潔だな。美しい。(気がする)
以上!