最近、DI、SL アンチパターン、AOP など、アプリケーションの設計パターンに関する多くの記事を読んでいました。この理由 - 私は設計の妥協点を見つけたいと思っています: 疎結合で、クリーンで、使いやすいです。DI は、コンストラクターまたはプロパティの汚染につながるクロスカッティングとオプションの依存関係という 1 つの問題を除いて、ほぼ解決策のようです。だから私はこれに対する私自身の解決策を持ってきて、あなたがそれについてどう思うか知りたい.
マーク シーマン (DI 本の著者であり、有名な「SL はアンチ パターン」という声明の著者) は、その本の中で、アンビエント コンテキストと呼ばれるパターンについて言及しています。あまり好きではないと彼は言いますが、このパターンは依然として興味深いものです。スコープがあり、デフォルト値を提供するため、null をチェックする必要がないことを除けば、古き良きシングルトンのようなものです。それには 1 つの欠陥があります - それはありませんし、そのスコープと自分自身を処分する方法について知ることができません。
では、ここで Service Locator を適用してみませんか? Ambient Context オブジェクトのスコーピングと破棄の両方の問題を解決できます。アンチパターンだと言う前に: コントラクトを隠すときです。しかし、私たちの場合、OPTIONAL コントラクトを非表示にしているので、IMO はそれほど悪くありません。
ここに私が何を意味するかを示すいくつかのコードがあります:
public interface ILogger
{
void Log(String text);
}
public interface ISomeRepository
{
// skipped
}
public class NullLogger : ILogger
{
#region ILogger Members
public void Log(string text)
{
// do nothing
}
#endregion
}
public class LoggerContext
{
public static ILogger Current
{
get
{
if(ServiceLocator.Current == null)
{
return new NullLogger();
}
var instance = ServiceLocator.Current.GetInstance<ILogger>();
if (instance == null)
{
instance = new NullLogger();
}
return instance;
}
}
}
public class SomeService(ISomeRepository repository)
{
public void DoSomething()
{
LoggerContext.Current.Log("Log something");
}
}
編集:具体的な質問をしないことは、スタックオーバーフローの設計と矛盾することを認識しています。したがって、この設計が悪い理由を最もよく説明している投稿を回答としてマークし、より良い解決策(または追加?)を提供します。しかし、AOP を提案しないでください。それは良いことですが、コード内で本当に何かをしたい場合には解決策ではありません。
編集 2: ServiceLocator.Current is null のチェックを追加しました。SL が構成されていない場合に既定の設定で動作するようにすることが、私のコードで意図していることです。