首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

規約模式 實作:用組合邏輯拆解複雜業務規則

     編輯:關於C#

當業務規則變得「可組合、可拆分、可重組」時,Specification Pattern(規約模式) 是領域驅動設計(DDD)中最經典的解法。本文以「書店租書驗證」為例:需同時滿足「未達最大租書數」與「帳號啟用中」兩條規則,展示如何將規則碎片化為獨立類別,再透過 And/Or/Not 邏輯運算子自由組合。

核心介面:ISpecification<T>

public interface ISpecification<T> {
    bool IsSatisfiedBy(T entity);
    ISpecification<T> And(ISpecification<T> other);
    ISpecification<T> Or(ISpecification<T> other);
    ISpecification<T> Not();
}

組合基類:CompositeSpecification<T>

public abstract class CompositeSpecification<T> : ISpecification<T> {
    public abstract bool IsSatisfiedBy(T entity);

    public ISpecification<T> And(ISpecification<T> spec) 
        => new AndSpecification<T>(this, spec);
    public ISpecification<T> Or(ISpecification<T> spec) 
        => new OrSpecification<T>(this, spec);
    public ISpecification<T> Not() 
        => new NotSpecification<T>(this);
}

邏輯運算子實作

public class AndSpecification<T> : CompositeSpecification<T> {
    private readonly ISpecification<T> _left, _right;
    public AndSpecification(ISpecification<T> left, ISpecification<T> right) {
        _left = left; _right = right;
    }
    public override bool IsSatisfiedBy(T entity) 
        => _left.IsSatisfiedBy(entity) && _right.IsSatisfiedBy(entity);
}

public class OrSpecification<T> : CompositeSpecification<T> { /* || */ }
public class NotSpecification<T> : CompositeSpecification<T> { /* ! */ }

具體業務規則

public class HasReachedMaxSpec : CompositeSpecification<Customer> {
    public override bool IsSatisfiedBy(Customer c) => c.TotalRentNumber >= 6;
}

public class CustomerActiveSpec : CompositeSpecification<Customer> {
    public override bool IsSatisfiedBy(Customer c) => c.Active;
}

客戶實體組合規則

public class Customer {
    private readonly ISpecification<Customer> _maxSpec, _activeSpec;
    public Customer(ISpecification<Customer> max, ISpecification<Customer> active) {
        _maxSpec = max; _activeSpec = active;
    }
    public int TotalRentNumber { get; set; }
    public bool Active => true; // 簡化

    public bool CanRent() {
        // 未達上限 AND 帳號啟用
        var spec = _maxSpec.Not().And(_activeSpec);
        return spec.IsSatisfiedBy(this);
    }
}

優缺點與適用時機

優點缺點/注意
規則單一職責、易測試、可動態組合簡單 if-else 反而更清楚時別濫用
符合開放封閉原則,新增規則不改舊碼過度拆解導致類別爆炸,需把握粒度
可序列化存庫,支援規則引擎/動態配置效能敏感路徑(如迴圈內萬次判斷)慎用

規約模式的精髓在於 「把業務規則變成一等公民」。下次看到 if (a && b && !c || d) 橫跨幾十行,請考慮拆成 SpecA.And(SpecB).And(SpecC.Not()).Or(SpecD)——程式碼會開始說人話。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved