精华帖 (0) :: 良好帖 (0) :: 新手帖 (19) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-30
最后修改:2009-11-30
规格模式是组合模式的一种扩展,在框架性开发中使用较多(项目级开发很少使用),这里做一个简单的介绍。由于是摘录,上下文章节可以参考我的博客,http://hi.baidu.com/cbf4life,或者下载PDF文件也一样。 发带格式、带图片的DOC文档太麻烦了,刚刚还出现了内容都整理好了,然后附件上传不上来,就在那转圈,我晕,只有重新发了!
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 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2009-12-01
没人顶,自己安慰一下吧
|
|
返回顶楼 | |
发表时间:2009-12-01
~我刚刚载下了,好好学学,嘿嘿
|
|
返回顶楼 | |
发表时间:2009-12-01
楼主辛苦了。
确实是挺有意思的一个模式,值得学习。 我感觉 它其实也是其他模式的一些组合吧?不过新提炼出一种来,确实也有他的独到之处。 |
|
返回顶楼 | |
发表时间: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个条件拼在一起的呢??没有看出来啊 |
|
返回顶楼 | |
发表时间:2009-12-02
基本上就是 Composite pattern
|
|
返回顶楼 | |
发表时间: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文件。 |
|
返回顶楼 | |
发表时间:2009-12-02
这个循序渐进的讲解方式很不错,估计楼主读了不少外国技术书籍
|
|
返回顶楼 | |
发表时间:2009-12-02
晕,少见多怪,人家都用了很多年了
|
|
返回顶楼 | |
发表时间:2009-12-02
具体的好处在哪,使用于什么具体的场景,解决什么样的问题,LZ能再说一下吗?
|
|
返回顶楼 | |