`
cbf4life
  • 浏览: 25908 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

23模式之外的模式——规格模式 Specification Pattern

阅读更多

     规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),这里做一个简单的介绍。由于是摘录,上下文章节可以参考我的博客,http://hi.baidu.com/cbf4life,或者下载PDF文件也一样。  发带格式、带图片的DOC文档太麻烦了,刚刚还出现了内容都整理好了,然后附件上传不上来,就在那转圈,我晕,只有重新发了!



      这里假设了一个这样一个场景,有一堆的User对象,UserProvider提供查询服务。们来看组合规格书(CompositeSpecification),它是一个抽象类,实现了与或非的操作,如下所示。

 

public abstract class CompositeSpecification implements IUserSpecification {
	//是否满足条件有实现类实现
	public abstract boolean isSatisfiedBy(User user);
	//and操作
	public IUserSpecification and(IUserSpecification spec) {
		return new AndSpecification(this,spec);
	}
	//not操作
	public IUserSpecification not() {
		return new NotSpecification(this);
	}
	//or操作
	public IUserSpecification or(IUserSpecification spec) {
		return new OrSpecification(this,spec);
	}
}

 

      候选对象是否满足条件是由isSatisfiedBy方法决定的,它代表的是一个判断逻辑,由各个实现类实现。三个与或非操作在抽象类中实现,它是通过直接new了一个子类,如此设计非常符合单一职责原则,每个子类都有一个独立的职责,要么完成与操作,要么完成或操作,要么完成非操作。我们先来看与操作规格书,如下所示。

 public class AndSpecification extends CompositeSpecification {

	//传递两个规格书进行and操作
	private IUserSpecification left;
	private IUserSpecification right;
	
	public AndSpecification(IUserSpecification _left,IUserSpecification _right){
		this.left = _left;
		this.right = _right;
	}
	//进行and运算
	@Override
	public boolean isSatisfiedBy(User user) {
		return left.isSatisfiedBy(user) && right.isSatisfiedBy(user);
	}
} 

      通过构造函数传递过来两个需要操作的规格书,然后通过isSatisfiedBy方法返回两者and操作结果。或规格书和非规格书与此类似,分别如下所示。

 

public class OrSpecification extends CompositeSpecification {
	//左右两个规格书
	private IUserSpecification left;
	private IUserSpecification right;
	
	public OrSpecification(IUserSpecification _left,IUserSpecification _right){
		this.left = _left;
		this.right = _right;
	}
	//or运算
	@Override
	public boolean isSatisfiedBy(User user) {
		return left.isSatisfiedBy(user) || right.isSatisfiedBy(user);
	}
}


public class NotSpecification extends CompositeSpecification {
	//传递一个规格书
	private IUserSpecification spec;
	
	public NotSpecification(IUserSpecification _spec){
		this.spec = _spec;
	}
	//not操作
	@Override
	public boolean isSatisfiedBy(User user) {
		return !spec.isSatisfiedBy(user);
	}
}
 

 

      该三个规格书都是不发生变化的,只要使用该框架,三个规格书都要实现的,而且代码基本上是雷同的,所以才有了父类依赖子类的设计,否则是严禁出现父类依赖子类的情况。大家再仔细看看这三个规格书和组合规格书,代码很简单,但也很巧妙,它跳出了我们面向对象设计的思维,不变部分使用一种固化方式实现。

名字相等、年龄大于基准年龄、Like格式等规格书都有少许改变,把实现接口变为继承基类,我们以名字相等规格书为例,如下所示。
public class UserByNameEqual extends CompositeSpecification {
	//基准姓名
	private String name;
	//构造函数传递基准姓名
	public UserByNameEqual(String _name){
		this.name = _name;
	}
	//检验用户是否满足条件
	public boolean isSatisfiedBy(User user) {
		return user.getName().equals(name);
	}
} 
      仅仅修改了黑体部分,其他没有任何改变。另外两个规格书修改相同,不再赘述。其他的User及UserProvider没有任何改动,不再赘述。
      我们修改一下场景类,如下所示。
public class Client {
	
	public static void main(String[] args) {
		//首先初始化一批用户
		ArrayList<User> userList = new ArrayList<User>();
		userList.add(new User("苏国庆",23));
		userList.add(new User("国庆牛",82));		
		userList.add(new User("张国庆三",10));
		userList.add(new User("李四",10));
		//定义一个用户查询类
		IUserProvider userProvider = new UserProvider(userList);
		//打印出名字包含国庆的人员
		System.out.println("===名字包含国庆的人员===");
		//定义一个规格
		IUserSpecification spec = new UserByAgeThan(25);
		IUserSpecification spec2 = new UserByNameLike("%国庆%");
		for(User u:userProvider.findUser(spec.and(spec2))){
			System.out.println(u);
		}
	}
} 
       在场景类中我们建立了两个规格书,一个是年龄大于25的用户,一个是名字中包含“国庆”两个字的用户,这两个规格书之间的关系是与关系,运行结果如下:

===名字包含国庆的人员===

用户名:国庆牛 年龄:82

  • 大小: 10.6 KB
分享到:
评论
17 楼 jiasky 2010-06-01  
楼主的举例生动有趣
   happyWithMan...
      KindWomen...
          makeEyesWithMan...
严重支持!
16 楼 Durian 2009-12-10  
头一次听说这种模式。
经典的23种之外应该还有各种变形和扩展,今天终于在这里应验了。
看来学武止境也。
15 楼 喜羊羊与灰太狼 2009-12-06  
喜羊羊与灰太狼 写道
怎么感觉和这个人说的是一样的呢?
http://www.cnblogs.com/bmrxntfj/archive/2008/02/17/1071359.html
这个是08年2月写的,难道是一个人?。。。

奥,刚才查了一下才知道,原来是ddd当中的specification pattern呀,不好意思哈
14 楼 喜羊羊与灰太狼 2009-12-06  
怎么感觉和这个人说的是一样的呢?
http://www.cnblogs.com/bmrxntfj/archive/2008/02/17/1071359.html
这个是08年2月写的,难道是一个人?。。。
13 楼 cbf4life 2009-12-03  
Jen 写道
晕,少见多怪,人家都用了很多年了



哇哦,用了很多年了,人家把框架写好了,你就用.or.and的用,那也是用。
12 楼 cbf4life 2009-12-03  
hatedance 写道
楼主讲的模式是不是跟hibernate的criteria的用法一个东西啊?
这种模式在自定义组合条件的查询器里经常要用到的。
 List cats = session.createCriteria(Cat.class)
     .add( Restrictions.like("name", "Iz%") )
     .add( Restrictions.gt( "weight", new Float(minWeight) ) )
     .addOrder( Order.asc("age") )
     .list();


是的,这里讲的是它的实现。
11 楼 hatedance 2009-12-03  
楼主讲的模式是不是跟hibernate的criteria的用法一个东西啊?
这种模式在自定义组合条件的查询器里经常要用到的。
 List cats = session.createCriteria(Cat.class)
     .add( Restrictions.like("name", "Iz%") )
     .add( Restrictions.gt( "weight", new Float(minWeight) ) )
     .addOrder( Order.asc("age") )
     .list();
10 楼 hankesi2000 2009-12-02  
具体的好处在哪,使用于什么具体的场景,解决什么样的问题,LZ能再说一下吗?
9 楼 Jen 2009-12-02  
晕,少见多怪,人家都用了很多年了
8 楼 weishuang 2009-12-02  
这个循序渐进的讲解方式很不错,估计楼主读了不少外国技术书籍
7 楼 cbf4life 2009-12-02  
streamfly 写道
想问下,最后main方法里 

# for(User u:userProvider.findUser(spec.and(spec2))){ 
#             System.out.println(u); 
#         } 

spec.and(spec2) 返回的应该是基于 IUserSpecification 接口的对象。从接口里唯一可以确定是2着是不是符合要求 isSatisfiedBy(User user),返回布尔值。怎么具体把2个条件拼在一起的呢??没有看出来啊



   产生了一个递归调用,你可以仔细看一下PDF文件。
6 楼 xly_971223 2009-12-02  
基本上就是 Composite pattern
5 楼 streamfly 2009-12-02  
想问下,最后main方法里 

# for(User u:userProvider.findUser(spec.and(spec2))){ 
#             System.out.println(u); 
#         } 

spec.and(spec2) 返回的应该是基于 IUserSpecification 接口的对象。从接口里唯一可以确定是2着是不是符合要求 isSatisfiedBy(User user),返回布尔值。怎么具体把2个条件拼在一起的呢??没有看出来啊
4 楼 sunjun 2009-12-02  
路过,顶 一下
3 楼 superhanliu 2009-12-01  
楼主辛苦了。
确实是挺有意思的一个模式,值得学习。
我感觉 它其实也是其他模式的一些组合吧?不过新提炼出一种来,确实也有他的独到之处。
2 楼 daxiong921 2009-12-01  
~我刚刚载下了,好好学学,嘿嘿
1 楼 cbf4life 2009-12-01  
没人顶,自己安慰一下吧

相关推荐

    specification 规格模式

    规格模式(Specification Pattern),是由Eric Evans和Martin Fowler共同提出的一个设计模式,主要用于封装对象的搜索标准和条件逻辑。该模式的核心思想是分离候选对象的选择声明与对候选对象的匹配过程。 在探讨该...

    利用Specification模式检索缓存数据

    6. `specification`:这个文件可能是Specification模式的基类或抽象类,定义了核心方法,如`and()`、`or()`,用于组合规格,以及`toPredicate()`方法,用于将Specification转换为可执行的查询。 在实际应用中,我们...

    23种设计模式,及设计模式的七种设计原则的文档和Java代码实现

    此外,规格模式(Specification Pattern)是一种行为模式,它允许以一种声明式的方式来表达业务规则,使得业务逻辑易于理解且易于组合。 在Java代码实现中,你可以找到每种模式的具体应用示例,这有助于你理解和...

    node-specification-pattern:NodeJS的规范模式实现

    NodeJS的规范模式 NodeJS的规范模式实现。 适用于任何种类的验证,可以简化,提高可重用性并使代码更清晰。 尽管主要用于以检查业务规则,但是组合规则的思想提供了很大的灵活性。 这是该模式JavaScript实现,包括...

    PXE首选资料——规格书

    PXE Specification Version 2.1 是这份文档的核心,详细定义了PXE的工作原理和规范。 PXE的运作流程大致分为以下几个步骤: 1. **初始化**:当计算机启动时,如果配置了PXE功能,BIOS会查找支持PXE的网络适配器,...

    Invalid Pattern Specification(亲测可用).md

    Invalid Pattern Specification(亲测可用).md

    LPDDR5 (6400M) specification

    LPDDR5(6400M)规格是JEDEC(固态技术协会)制定的一种低功耗双数据速率5代内存标准,旨在提高移动设备和嵌入式系统的内存性能,同时降低能耗。JESD209-5是该标准的具体版本,发布于2019年2月。LPDDR5的引入对现代...

    design pattern

    本文档深入探讨了设计模式的形式化,特别是通过Balanced Pattern Specification Language (BPSL)对设计模式进行结构和行为方面的正式描述。此外,它还关注于设计模式的组合,即如何将两个或更多的模式整合在一起以...

    specification-pattern-example:一个如何在Java中实现规范模式的示例

    如您所料,将SQL / HQL代码直接放入Specification对象不是一个好习惯,因为它破坏了数据与基础结构的明确分离。 可以选择实现知道如何将每个规范及其组合转换为SQL / HQL查询的转换器(请参阅Spring的...

    PMBus Specification Part I 规格书

    PMBUS Power System Management Protocol Specification Part I – General Requirements, Transport And Electrical Interface

    Cisco USGMII Specification Rev4.2

    * USGMII 接口支持全双工模式,而网络接口则支持半双工和全双工模式。 * 能够发送 Packet Channel Header,以支持可编程的信息交换 между PHY 和 MAC,例如从 PHY 到 MAC 的 PTP 时间戳,以提高加密的 PTP ...

    PCIe M.2 specification规格书.7z

    总之,PCIe M.2 specification规格书是一本全面的技术文档,包含了设计和开发M.2接口设备所需的所有关键信息。无论是为新的笔记本电脑设计M.2 SSD插槽,还是为扩展卡开发新的功能,这个规格书都是不可或缺的参考资料...

    ASP.NET设计模式-杨明军译(源码)

    5.2.1 Specification模式 5.2.2 Composite模式 5.2.3 Layer Supertype模式 5.3 应用设计原则 5.3.1 依赖倒置原则和依赖注入模式 5.3.2 接口分离原则 5.3.3 里氏替换原则 5.4 小结 第6章 服务层 6.1 服务...

    Laravel开发-laravel-specification

    Specification模式的核心思想是将复杂的业务逻辑转换为一系列简单的、可复用的规格(Specification)对象。这些规格对象可以根据需要进行组合,形成更复杂的查询条件。在Laravel中,我们可以使用这一模式来处理数据...

    SSD9——Software Specification, Testing, and Maintenance

    ### SSD9 —— 软件规范、测试与维护 #### 课程介绍 SSD9是一门关于软件工程的基础课程,旨在让学生深入了解软件工程的基本原则和实践方法,从而提高软件产品的质量并使得软件开发过程更加可预测且经济高效。本...

    Devicetree Specification 设备树规格书

    设备树规格书是官方文档,详细阐述了设备树的语法、结构以及使用方法。下面我们将深入探讨设备树的相关知识点。 1. **设备树的基本概念** 设备树是一种数据结构,由一系列节点和属性组成,用于描述硬件平台的组成...

    Reconciling Exhaustive Pattern Matching with Objects

    文章指出,尽管模式匹配是现代函数式编程语言的重要特性,但它与面向对象语言的中心目标——数据抽象和可扩展性——存在冲突。模式匹配允许根据数据的结构来执行不同的操作,这在处理代数数据类型(如树、列表等)时...

    OV5693 PRODUCT SPECIFICATION产品规格书

    ov9653 PRODUCT SPECIFICATION,开发手册。包含signal descriptions、system level description、block level description、image sensor core digital functions、image sensor processor digital functions、...

Global site tag (gtag.js) - Google Analytics