前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之规格模式

设计模式之规格模式

作者头像
beginor
发布2020-08-10 14:51:44
9630
发布2020-08-10 14:51:44
举报

设计模式之规格模式

在计算机程序中, 规格模式是一种特殊的软件设计模式业务规则可以使用布尔逻辑组成规则连而重新组合, 这种模式通常在领域驱动设计中使用。

规格模式描述的是一个业务规则可以和另外的业务规则聚合, 在这种模式中, 业务逻辑单元继承自可聚合的抽象规格基类类,该基类有一个返回布尔值的方法 IsSatisfiedBy 。 在初始化之后, 规格可以和其它规格进行逻辑组合, 使新的规格很容易维护, 实现高度自定义的业务逻辑。

规格模式的 UML 图如下:

规格模式
规格模式

实现代码如下:

代码语言:javascript
复制
public interface ISpecification<TTarget> {

    bool IsSatisfiedBy(TTarget candidate);

    ISpecification<TTarget> And(ISpecification<TTarget> specification);

    ISpecification<TTarget> Or(ISpecification<TTarget> specification);

    ISpecification<TTarget> Not(ISpecification<TTarget> specification);

}

上面是规格模式的接口定义, 通常会实现一个抽象的 CompositSpecification 做为基类, 代码如下:

代码语言:javascript
复制
public abstract class CompositSpecification<TTarget> : ISpecification<TTarget> {

    public abstract bool IsSatisfiedBy(TTarget candidate);

    public ISpecification<TTarget> And(ISpecification<TTarget> specification) {
        return new AndSpecification<TTarget>(this, specification);
    }

    public ISpecification<TTarget> Or(ISpecification<TTarget> specification) {
        return new OrSpecification<TTarget>(this, specification);
    }

    public ISpecification<TTarget> Not(ISpecification<TTarget> specification) {
        return new NotSpecification<TTarget>(specification);
    }

}

AndSpecification 实现两种规格通过逻辑与尽兴组合:

代码语言:javascript
复制
public class AndSpecification<TTarget> : CompositSpecification<TTarget> {

    readonly ISpecification<TTarget> x;
    readonly ISpecification<TTarget> y;

    public AndSpecification(ISpecification<TTarget> x, ISpecification<TTarget> y) {
        this.x = x;
        this.y = y;
    }

    public override bool IsSatisfiedBy(TTarget candidate) {
        return x.IsSatisfiedBy(candidate) && y.IsSatisfiedBy(candidate);
    }

}

OrSpecification 实现两种规格通过逻辑或进行组合:

代码语言:javascript
复制
public class OrSpecification<TTarget> : CompositSpecification<TTarget> {

    readonly ISpecification<TTarget> x;
    readonly ISpecification<TTarget> y;

    public OrSpecification(ISpecification<TTarget> x, ISpecification<TTarget> y) {
        this.x = x;
        this.y = y;
    }

    public override bool IsSatisfiedBy(TTarget candidate) {
        return x.IsSatisfiedBy(candidate) || y.IsSatisfiedBy(candidate);
    }

}

NotSpecification 实现规格的逻辑否:

代码语言:javascript
复制
public class NotSpecification<TTarget> : CompositSpecification<TTarget> {

    readonly ISpecification<TTarget> x;

    public NotSpecification(ISpecification<TTarget> x) {
        this.x = x;
    }

    public override bool IsSatisfiedBy(TTarget candidate) {
        return !x.IsSatisfiedBy(candidate);
    }

}

至此, 规格模式就基本上实现了, 不过实际使用中, 通常会实现一个范型的规格模式作为入口, 代码如下:

代码语言:javascript
复制
public class ExpressionSpecification<TTarget> : CompositSpecification<TTarget> {

    readonly Func<TTarget, bool> expression;

    public ExpressionSpecification(Func<TTarget, bool> expression) {
        this.expression = expression;
    }

    public override bool IsSatisfiedBy(TTarget candidate) {
        return expression(candidate);
    }

}

现在看一个实际的例子, 我们有一些手机, 代码如下:

代码语言:javascript
复制
var mobiles = new List<Mobile>() {
    new Mobile(MobileBrand.Apple, MobileType.Smart),
    new Mobile(MobileBrand.Samsung, MobileType.Smart),
    new Mobile(MobileBrand.Samsung, MobileType.Basic)
};

使用规格模式选出所有的智能手机, 代码如下:

代码语言:javascript
复制
var smartSpecification = new ExpressionSpecification<Mobile>(
    mobile => mobile.Type == MobileType.Smart
);
// find all smart mobiles;
var smartMobiles = mobiles.FindAll(
    mobile => smartSpecification.IsSatisfiedBy(mobile)
);

使用两种规格模式进行逻辑与组合, 选出品牌是 Apple 的智能手机, 代码如下:

代码语言:javascript
复制
var appleSpecification = new ExpressionSpecification<Mobile>(
    mobile => mobile.Brand = MobileBrand.Apple
);

// find all apple smart mobiles;
var andSpecification = new AndSpecification<Mobile>(
    smartSpecification, appleSpecification
);
var appleSmartMobiles = mobiles.FindAll(
    mobile => andSpecification.IsSatisfiedBy(mobile)
);

值得一提的是, .NET 3.5 之后引入的 Linq 就是基于规格模式的, 可以说是规格模式的典范。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计模式之规格模式
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档