本文节选自《设计模式就该这样学》

1 规格模式的定义

规格模式(Specification Pattern)可以认为是组合模式的一种扩展。很多时候程序中的某些条件决定了业务逻辑,这些条件就可以抽离出来以某种关系(与、或、非)进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,通过预定义多个条件,然后使用这些条件的组合来处理查询或过滤,而不是使用逻辑判断语句来处理,可以简化整个实现逻辑。

这里的每个条件都是一个规格,多个规格(条件)通过串联的方式以某种逻辑关系形成一个组合式的规格。规格模式属于结构型设计模式。

2 规格模式的应用场景

规格模式主要适用于以下应用场景。

(1)验证对象,检验对象本身是否满足某些业务要求或者是否已经为实现某个业务目标做好了准备。

(2)从集合中选择符合特定业务规则的对象或对象子集。

(3)指定在创建新对象的时候必须要满足某种业务要求。

3 规格模式的UML类图

规格模式的UML类图如下图所示。

由上图可以看到,规格模式主要包含6个角色。

(1)抽象规格书(Specification):对规格书的抽象定义。

(2)组合规格书(CompositeSpecification):一般设计为抽象类,对规格书进行与或非操作,实现and()、or()、not()方法,在方法中关联子类,因为子类为固定类,所以父类可以进行关联。

(3)与规格书(AndSpecification):对规格书进行与操作,实现isSatisfiedBy()方法。

(4)或规格书(OrSpecification):对规格书进行或操作,实现isSatisfiedBy()方法。

(5)非规格书(NotSpecification):对规格书进行非操作,实现isSatisfiedBy()方法。

(6)业务规格书(BizSpecification):实现isSatisfiedBy()方法,对业务进行判断,一个类为一种判断方式,可进行扩展。

4 规格模式的通用写法

以下是规格模式的通用写法。


public class Client { public static void main(String[] args) {
//待分析的对象
List<Object> list = new ArrayList<Object>();
//定义两个业务规格书
ISpecification spec1 = new BizSpecification("a");
ISpecification spec2 = new BizSpecification("b");
//规格调用
for (Object o : list) {
if(spec1.and(spec2).isSatisfiedBy(o)){ //如果o满足spec1 && spec2
System.out.println(o);
}
}
} //抽象规格书
interface ISpecification {
//候选者是否满足条件
boolean isSatisfiedBy (Object candidate) ;
//and操作
ISpecification and (ISpecification spec);
//or操作
ISpecification or (ISpecification spec);
//not操作
ISpecification not ();
} //组合规格书
static abstract class CompositeSpecification implements ISpecification {
//是否满足条件由子类实现
public abstract boolean isSatisfiedBy (Object candidate) ;
//and操作
public ISpecification and (ISpecification spec) {
return new AndSpecification(this, spec);
}
//or操作
public ISpecification or(ISpecification spec) {
return new OrSpecification(this, spec);
}
//not操作
public ISpecification not() {
return new NotSpecification(this);
}
} //与规格书
static class AndSpecification extends CompositeSpecification {
//传递两个规格书进行and操作
private ISpecification left;
private ISpecification right; public AndSpecification(ISpecification left, ISpecification right) {
this.left = left;
this.right = right;
} //进行and运算
public boolean isSatisfiedBy(Object candidate) {
return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate);
}
} static class OrSpecification extends CompositeSpecification {
//传递两个规格书进行or操作
private ISpecification left;
private ISpecification right; public OrSpecification(ISpecification left, ISpecification right) {
this.left= left;
this.right = right;
} //进行or运算
public boolean isSatisfiedBy(Object candidate) {
return left.isSatisfiedBy(candidate) || right.isSatisfiedBy(candidate);
}
} static class NotSpecification extends CompositeSpecification {
//传递两个规格书进行非操作
private ISpecification spec; public NotSpecification(ISpecification spec) {
this.spec = spec;
} //进行not运算
public boolean isSatisfiedBy(Object candidate) {
return !spec.isSatisfiedBy(candidate);
}
} //业务规格书
static class BizSpecification extends CompositeSpecification {
//基准对象,如姓名等,也可以是int等类型
private String obj;
public BizSpecification(String obj) {
this.obj = obj;
}
//判断是否满足要求
public boolean isSatisfiedBy(Object candidate){
//根据基准对象判断是否符合
return true;
}
}
}

5 规格模式的优缺点

5.1 优点

规格模式非常巧妙地实现了对象筛选功能,适合在多个对象中筛选查找,或者业务规则不适于放在任何已有实体或值对象中,而且规则变化和组合会掩盖对象的基本含义的情况。

5.2 缺点

规格模式中有一个很严重的问题就是父类依赖子类,这种情景只有在非常明确不会发生变化的场景中存在,它不具备扩展性,是一种固化而不可变化的结构。一般在面向对象设计中应该尽量避免。

关注微信公众号『 Tom弹架构 』回复“设计模式”可获取完整源码。

【推荐】Tom弹架构:30个设计模式真实案例(附源码),挑战年薪60W不是梦

本文为“Tom弹架构”原创,转载请注明出处。技术在于分享,我分享我快乐!

如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。关注微信公众号『 Tom弹架构 』可获取更多技术干货!

规格模式(Specification Pattern)的更多相关文章

  1. 规约模式(Specification Pattern)

    前期准备之规约模式(Specification Pattern) 一.前言 在专题二中已经应用DDD和SOA的思想简单构建了一个网上书店的网站,接下来的专题中将会对该网站补充更多的DDD的内容.本专题 ...

  2. [.NET领域驱动设计实战系列]专题三:前期准备之规约模式(Specification Pattern)

    一.前言 在专题二中已经应用DDD和SOA的思想简单构建了一个网上书店的网站,接下来的专题中将会对该网站补充更多的DDD的内容.本专题作为一个准备专题,因为在后面一个专题中将会网上书店中的仓储实现引入 ...

  3. 规约模式Specification Pattern

    什么是规约模式 规约模式允许我们将一小块领域知识封装到一个单元中,即规约,然后可以在code base中对其进行复用. 它可以用来解决在查询中泛滥着GetBySomething方法的问题,以及对查询条 ...

  4. 规约模式(Specification Pattern)

    一.引言 最近在看一个项目的源码时(DDD),对里面的一些设计思想和设计思路有了一些疑问.当看到(Repository层)中使用了 spec.SatisfiedBy() 时,感觉有点懵.于是在项目中搜 ...

  5. 设计模式(十二):通过ATM取款机来认识“状态模式”(State Pattern)

    说到状态模式,如果你看过之前发布的重构系列的文章中的<代码重构(六):代码重构完整案例>这篇博客的话,那么你应该对“状态模式”并不陌生,因为我们之前使用到了状态模式进行重构.上一篇博客我们 ...

  6. 设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)

    上篇博客我们从醋溜土豆丝与清炒苦瓜中认识了“模板方法模式”,那么在今天这篇博客中我们要从电影院中来认识"迭代器模式"(Iterator Pattern).“迭代器模式”顾名思义就是 ...

  7. 设计模式(一):“穿越火线”中的“策略模式”(Strategy Pattern)

    在前段时间呢陆陆续续的更新了一系列关于重构的文章.在重构我们既有的代码时,往往会用到设计模式.在之前重构系列的博客中,我们在重构时用到了“工厂模式”.“策略模式”.“状态模式”等.当然在重构时,有的地 ...

  8. Net设计模式实例之原型模式( Prototype Pattern)

    一.原型模式简介(Brief Introduction) 原型模式(Prototype Pattern):用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. Specify the kin ...

  9. 代理模式(Proxy pattern)

    代理模式(proxy pattern):作用:为其他对象提供一种代理,以控制对这个对象的访问.代理对象在客户端对象和目标对象之间起中介的作用. 代理模式涉及到的角色: 抽象角色:声明真实对象和代理对象 ...

随机推荐

  1. C#开发BIMFACE系列52 CS客户端集成BIMFACE应用的技术方案

    BIMFACE二次开发系列目录     [已更新最新开发文章,点击查看详细] 在我的博客<C#开发BIMFACE系列49 Web网页集成BIMFACE应用的技术方案>.<C#开发BI ...

  2. airtest keyevent 按键速查表

  3. BUAA软件工程:软件案例分析

    BUAA软件工程:软件案例分析 Author:17373015 乔玺华 项目 内容 这个作业属于哪个课程 2020计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 软件案例分析博客作业 我在这个 ...

  4. Vue项目搭建常用的配置文件,request.js和vue.config.js

    request.js用来请求数据,封装的代码如下: import axios from 'axios' const request = axios.create({ timeout: 5000 }) ...

  5. Noip模拟61 2021.9.25

    T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...

  6. 所驼门王的宝藏(Tarjan)

    题目描述 在宽广的非洲荒漠中,生活着一群勤劳勇敢的羊驼家族.被族人恭称为"先知"的Alpaca L. Sotomon是这个家族的领袖,外人也称其为"所驼门王". ...

  7. 关于string转换为wstring问题

    方法一:需要调用windows的api函数进行转换,在vs2017上试验转换成功 #ifdef _MSC_VER #include <Windows.h> #endif // _MSC_V ...

  8. IPv6(诞生原因、数据报格式、与IPv4的不同、地址表现形式、基本地址类型、IPv6与IPv4的过渡策略)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105297642 学习课程:<2019王道考研计算机网络> 学习目的 ...

  9. OKhttp3的使用教程

    首先在build.gradle下的dependencies下添加引用. implementation "com.squareup.okhttp3:okhttp:4.9.0" 然后编 ...

  10. PWN学习之格式化字符串漏洞

    目录 PWN学习之格式化字符串漏洞 格式化输出函数 格式化字符串漏洞 漏洞利用 使程序崩溃 栈数据泄露 任意地址内存泄漏 栈数据覆盖 任意地址内存覆盖 PWN学习之格式化字符串漏洞 格式化输出函数 可 ...