2010-07-12 26 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可以將你的閉包轉換爲規則。或者可能是一個將閉包轉換爲規則的擴展方法。