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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值