如何根据我的要求使用规范模式?

use*_*072 2 c# design-patterns specification-pattern

我已经阅读了规范模式的一些示例,但很难理解如何使用此模式实现.

我正在为客户开发一个庞大的程序.我需要从特定的银行导入XML文件,然后对每个文件进行验证.分类帐代码有不同的方法(subs,bo,rcc).因此,当文件读取SUBS时,它应该发送到SUBS方法.

这里的例子:

接口:

  • BlackBank
  • BlueBank
  • 雷德班克

分类帐代码:

  • SUBS
  • BO
  • RCC

结果:

  • BlackBank有SUBS,BO和RCC
  • BlueBank有SUBS
  • RedBank有BO和RCC

你能给出一些示例代码或指出我正确的方向吗?

T I*_*T I 10

如果没有上下文,这很难回答,所以我会尝试围绕我的信息做一些事情,希望它会给你一个想法.

像这样创建一个简单的规范界面

interface ISpecification<T>
{
    IsSatisfiedBy(T obj);
}
Run Code Online (Sandbox Code Playgroud)

假装你有一个"银行"的基本界面

interface IBank
{
    LedgerCode LedgerCode { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

还有一个LedgerCodes的枚举

[Flags]
enum LedgerCodes
{
    SUBS, BO, RCC
} 
Run Code Online (Sandbox Code Playgroud)

您可以制作一个简单的分类帐代码规范来检查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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在适当的地方,您可以使用您的规范,在这里我使用它来提供简单的验证.另一个用途是"选择",例如从存储库获取数据

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);
        }
    } 
}
Run Code Online (Sandbox Code Playgroud)

最后一些代码可以快速测试/演示上面的内容

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
    }
}
Run Code Online (Sandbox Code Playgroud)

网上有一些很好的例子,可以添加扩展方法,也可以覆盖运算符,以提供简洁易懂的自然可读规范,例如

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我目前使用该模式的方式可能有点过分,但我喜欢删除,重用和通常使逻辑更加OO的想法.

编辑:在阅读了一些评论后,您的问题似乎与一般的调度问题更相关,而不是规范模式.鉴于您的界面,您可以更简单地做.

class BankFacade
{
    public Send(IBlueBank bank)
    {
        // validate with specification
        // do stuff with IBlueBank
    }

    public Send(IRedBank bank)
    {
        // validate with specification
        // do stuff with IRedBank
    }

    //...
}
Run Code Online (Sandbox Code Playgroud)

多思考一下,你可以做些什么

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);
            }
        }

        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,你可能并不真的需要这种模式,你不应该试图将问题塞进去