2

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

我正在为客户开发一个庞大的程序。我需要从特定银行导入 XML 文件,然后对每个文件进行验证。Ledger Codes 有不同的方法(subs、bo、rcc)。所以当一个文件读取 SUBS 时,它应该发送到一个 SUBS 方法。

这里的例子:

接口:

  • 黑银行
  • 蓝色银行
  • 红银行

分类帐代码:

  • 潜艇
  • 碾压混凝土

结果:

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

您能否提供一些示例代码或指出正确的方向?

4

1 回答 1

10

如果没有上下文,这很难回答,所以我会尝试围绕我所拥有的信息编造一些东西,希望它能给你一个想法。

像这样创建一个简单的规范接口

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

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

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

网上有一些很好的例子,添加了扩展方法和覆盖操作符,以提供简洁且更自然易读的规范,例如

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

        //...
    }
}

但是您可能并不真正需要该模式,并且您不应该尝试将问题硬塞到其中

于 2013-06-02T14:21:33.213 回答