文脈がないと答えるのは難しいので、私が持っている情報に基づいて何かを作ってみます。
このような単純な仕様インターフェースを作成します
interface ISpecification<T>
{
IsSatisfiedBy(T obj);
}
次のような「銀行」の基本インターフェースがあるふりをします
interface IBank
{
LedgerCode LedgerCode { get; set; }
}
LedgerCodes の列挙型
[Flags]
enum LedgerCodes
{
SUBS, BO, RCC
}
IBank の LedgerCodes をチェックするための単純なレジャー コード仕様を作成できます (これは非常に一般的であり、ニーズに合わせて特定する必要があります)。
class LedgerCodeSpec : ISpecification<IBank>
{
private LedgerCode code;
public LedgerCodeSpecification(LedgerCode code)
{
this.code = code
}
public override bool IsSatisfiedBy(IBank obj)
{
return obj.LedgerCode == code;
}
}
必要に応じて仕様を使用できます。ここでは、簡単な検証を提供するために使用します。もう 1 つの用途は、リポジトリからデータを取得するなどの「選択」です。
class Bank : IBank
{
private ISpecification<IBank> spec;
private LedgerCode code;
public Bank(ISepcification<IBank> spec)
{
this.code = code;
this.spec = spec;
}
public LedgerCode LedgerCode { get; set; }
public bool IsValid
{
get
{
return spec.IsSatisfiedBy(this);
}
}
}
最後に、上記をすばやくテスト/デモするためのコード
class Main
{
public static void Main()
{
var spec = new LedgerCodeSpec(LedgerCodes.SUB)
var blueBank = new Bank(spec);
Console.WriteLine(blueBank.IsValid); // false
blueBank.LedgerCode = LedgerCodes.RCC | LedgerCodes.SUB;
Console.WriteLine(blueBank.IsValid); // false
blueBank.LedgerCode = LedgerCodes.SUB;
Console.WriteLine(blueBank.IsValid); // true
}
}
拡張メソッドを追加し、演算子をオーバーライドして、簡潔でより自然に読みやすい仕様を提供する Web 上のいくつかの良い例があります。
class MessageSpecification : Specification<string>
{
public const int MIN_LENGTH = 5;
public const int MAX_LENGTH = 60;
public override bool IsSatisfiedBy(string s)
{
Specification<string> length = new LengthSpecification(MIN_LENGTH, MAX_LENGTH);
Specification<string> isNull = new IsNullSpecification<string>();
Specification<string> spec = length && !isNull;
return spec.IsSatisfiedBy(s);
}
}
私が現在パターンを使用している方法はおそらくやり過ぎですが、ロジックを削除して再利用し、一般的にオブジェクト指向にするというアイデアが好きです。
編集:コメントのいくつかを読んだ後、問題は仕様パターンではなく、一般的なディスパッチの問題に関連しているようです。インターフェイスがあれば、もっと簡単に実行できます。
class BankFacade
{
public Send(IBlueBank bank)
{
// validate with specification
// do stuff with IBlueBank
}
public Send(IRedBank bank)
{
// validate with specification
// do stuff with IRedBank
}
//...
}
もう少し考えて、次のようなことができるかもしれません
class Parser
{
static class RedBankSpecification : ISpecification<XElement>
{
public override bool IsSatisfiedBy(XElement element)
{
return element.Value.equals("RED");
}
}
public void Parse(XDocument doc)
{
var rspec = new RedBankSpecification();
foreach(XElement e in doc)
{
if (r.IsSatisfiedBy(e))
{
IRedBank bank = new RedBank(e);
bankFacade.Send(bank);
}
}
//...
}
}
ただし、そのパターンは実際には必要ない可能性があり、問題をそれに押し込めようとするべきではありません