2010-07-12 25 views
4

我有我想要能够处理的“规则”的概念。因此,我创建了以下接口:闭包vs课?

public interface IRule<T> 
    { 
    Boolean IsSatisfiedBy(T value); 
    String GetViolationMessage(T value); 
    } 

我曾计划创造了一系列的“规则”的类来表示当前系统所支持,如各种规则:

public class MatchesPatternRule : IRule<String> 
    { 
    private readonly Regex _regex; 
    private readonly String _pattern; 

    public MatchesPatternRule(String pattern) 
    { 
     Verify.IsFalse(String.IsNullOrWhiteSpace(pattern)); 

     _regex = new Regex(pattern); 
     _pattern = pattern; 
    } 

    public Boolean IsSatisfiedBy(String value) 
    { 
     return _regex.IsMatch(value); 
    } 

    public String GetViolationMessage(String value) 
    { 
     return String.Format(RuleMessage.MatchesPatternViolation, _pattern, value); 
    } 
    } 

然后

public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern) 
{ 
    context.AddRule(new MatchesPatternRule(pattern)); 
    return context; 
} 

不过,我现在有20多个规则的计划,以及MatchesPatternRule类可以被很容易地更换:规则将通过各种推广方法,如消耗写作扩展方法为:

public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern) 
    where T : IComparable 
{ 
    Verify.IsFalse(String.IsNullOrWhiteSpace(pattern)); 

    Regex regex = new Regex(pattern); 
    context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value)); 
    return context; 
} 

好奇哪种方法更好,为什么?两者都很容易被抵制,并最终达到最终结果。任何有识之士将不胜感激!

UPDATE

基于从汤姆的意见,我想我已经选择去同一个中间路线的做法。我将创建一个静态类来保存每个“规则”的扩展方法。这将确保任何给定的规则很容易找到,并将保持我的代码组织,但也减少总体代码量。

public static class MatchesPatternRule 
    { 
    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern) 
    { 
     return MatchesPattern<T>(context, pattern, pattern, RegexOptions.None); 
    } 

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern) 
    { 
     return MatchesPattern<T>(context, pattern, friendlyPattern, RegexOptions.None); 
    } 

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, RegexOptions options) 
    { 
     return MatchesPattern<T>(context, pattern, pattern, options); 
    } 

    public static ValidationContext<String> MatchesPattern(this ValidationContext<String> context, String pattern, String friendlyPattern, RegexOptions options) 
    { 
     Verify.IsFalse(String.IsNullOrWhiteSpace(pattern)); 

     Regex regex = new Regex(pattern); 
     context.AddRule(value => regex.IsMatch(value), value => String.Format(RuleMessage.MatchesPatternViolation, _pattern, value)); 

     return context; 
    } 
    } 

回答

1

我不是C#用户,但在Ruby和Scala中,有一个类似的选择。拥有一个类似于这个上下文的特定接口的类似乎与封闭类似,虽然有更多的样板。因为他们在技术上追求相同的目标,那么问题当然会成为上下文最适合社交的问题。

是谁应该写这些规则足够聪明,让他们的头靠近关闭?否则,基于类的解决方案可能会更好用。如果我不喜欢我的Java程序员试图理解所有这些C#范例,那么基于类的解决方案可能比学习所有这些奇怪功能的东西容易一些 - 我知道奇怪的功能性东西,但我可以想像我自己不是知道它!只有你可以决定哪些人最适合将要写规则的人。如果你是唯一一个不得不写规则的人,那就疯了!选择你喜欢的任何美学。

文档和元数据如何?未来的可扩展性?如果您需要为规则添加额外的字段会怎么样?在基于闭包的解决方案上记录基于类的解决方案更容易吗?如果你必须找到并改变一个规则,哪一个会更容易呢?

1

为什么你不能同时拥有?对于简单的规则,你可以使用闭包。 ValidationContext.AddRule可以将你的闭包转换为规则。或者可能是一个将闭包转换为规则的扩展方法。