打字猴:1.700484e+09
1700484000 //or操作
1700484001
1700484002 public IUserSpecification or(IUserSpecification spec);
1700484003
1700484004 //not操作
1700484005
1700484006 public IUserSpecification not();
1700484007
1700484008 }
1700484009
1700484010 在规格书接口中增加了与或非的操作,接口修改了,实现类当然也要修改。先全面思考一下业务,与或非是不可扩展的操作,规格书(也就是规格对象)之间的操作只有这三种方法,是不需要扩展也不用预留扩展空间的。如此,我们就可以把与或非的实现放到基类中,那现在的问题变成了怎么在基类中实现与或非。注意看它们的返回值都需要返回规格书类型,很明显,我们在这里要用到递归调用了。可以这样理解,基类需要子类提供业务逻辑支持,因为基类是一个抽象类,不能实例化后返回,我们把简单类图画出来,如图37-3所示。
1700484011
1700484012
1700484013
1700484014
1700484015 图37-3 与规格的示意
1700484016
1700484017 基类对子类产生了依赖,然后进行递归计算,大家一定会发出这样的疑问:父类怎么可能依赖子类,这还是面向接口编程吗?想想看,我们提出面向接口编程的目的是什么?是为了适应变化,拥抱变化,对于不可能发生变化的部分为什么不能固化呢?与或非操作符号还会增加修改吗?规格书对象之间的操作还有其他吗?思考清楚这些问题后,答案就迎刃而解了。
1700484018
1700484019 注意 父类依赖子类的情景只有在非常明确不会发生变化的场景中存在,它不具备扩展性,是一种固化而不可变化的结构。
1700484020
1700484021 分析完毕,我们设计出详细的类图,如图37-4所示。
1700484022
1700484023
1700484024
1700484025
1700484026 图37-4 完整规格书类图
1700484027
1700484028 可能大家有很多的疑问,我们先来分析代码,代码分析完毕估计能解决你大部分的疑问。规格书接口如代码清单37-15所示,不再赘述。我们来看组合规格书(CompositeSpecification),它是一个抽象类,实现了与或非的操作,如代码清单37-16所示。
1700484029
1700484030 代码清单37-16 组合规格书
1700484031
1700484032 public abstract class CompositeSpecification implements IUserSpecification{
1700484033
1700484034 //是否满足条件由实现类实现
1700484035
1700484036 public abstract boolean isSatisfiedBy(User user);
1700484037
1700484038 //and操作
1700484039
1700484040 public IUserSpecification and(IUserSpecification spec){
1700484041
1700484042 return new AndSpecification(this,spec);
1700484043
1700484044 }
1700484045
1700484046 //not操作
1700484047
1700484048 public IUserSpecification not(){
1700484049
[ 上一页 ]  [ :1.700484e+09 ]  [ 下一页 ]