如何为我的需求使用规范模式

本文关键字:范模式 模式 我的 需求 | 更新日期: 2023-09-27 18:16:23

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

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

例子:

接口:

  • BlackBank
  • BlueBank
  • RedBank

分类代码:

  • 潜艇
  • RCC
结果:

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

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

如何为我的需求使用规范模式

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

创建如下的简单规范接口

interface ISpecification<T>
{
    IsSatisfiedBy(T obj);
}

假设你有一个'banks'的基本接口,看起来像

interface IBank
{
    LedgerCode LedgerCode { get; set; }
}

和一个枚举的LedgerCodes

[Flags]
enum LedgerCodes
{
    SUBS, BO, RCC
} 

你可以制作一个简单的分类帐代码规范来检查IBank的分类帐代码(这是相当普遍的,你需要根据你的需要制作它)

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

在网络上有一些很好的例子,添加扩展方法和覆盖操作符来提供一个简洁的,imo更自然可读的规范,例如

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

但是你可能并不真的需要这个模式你不应该把问题硬塞进去