GoF著作中未提到的设计模式(6):Specification

在一个较为复杂的业务流程中,某些条件的满足与否决定了业务逻辑的走向,我们可以把这些条件抽离出来,使得任意个条件以某种关系进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,我们也可以预定义多个条件,使用这些条件的组合来处理查询逻辑,而不是使用逻辑判断语句来处理,那样只会让代码变得复杂,让脑袋变大。
在Specification设计模式中,一个条件就是一个specification,多个specification通过串联的方式以某种逻辑关系形成一个组合式的specification。首先看一下整体的UML图:
GoF著作中未提到的设计模式(6):Specification
下面是Specification接口的声明:
public interface Specification { boolean isSatisfiedBy(Object params); Specification and(Specification other); Specification or(Specification other); Specification not(); }
它定义了各个条件间可用的关系:与、或、非,这三个关系所对应方法的返回值都是Specification自身,目的是为了实现Specification之间的串联(chaining),从而形成一个关系表达式,后面会看到具体的用法。isSatisfiedBy就是判定方法,参数是一个Object,支持任意类型。 下面我们来看CompositSpecification的声明:
public abstract class CompositeSpecification implements Specification{ @Override public Specification and(Specification other) { return new AndSpecification(this, other); } public abstract boolean isSatisfiedBy(Object params); @Override public Specification not() { return new NotSpecification(this); } @Override public Specification or(Specification other) { return new OrSpecification(this, other); } }
它实现了Specification接口的关系判定方法,而isSatisfiedBy则仍是抽象方法,需要派生类来具体实现。下面是三个分别实现了与、或、非关系判定的派生类的声明:
public class AndSpecification extends CompositeSpecification { private final Specification b; private final Specification a; public AndSpecification(Specification a,Specification b) { this.a = a; this.b = b; } @Override public boolean isSatisfiedBy(Object params) { return a.isSatisfiedBy(params) && b.isSatisfiedBy(params); } } public class OrSpecification extends CompositeSpecification { private final Specification b; private final Specification a; public OrSpecification(Specification a, Specification b) { this.a = a; this.b = b; } @Override public boolean isSatisfiedBy(Object params) { return a.isSatisfiedBy(params) || b.isSatisfiedBy(params); } } public class NotSpecification extends CompositeSpecification { private final Specification a; public NotSpecification(Specification a) { this.a = a; } @Override public boolean isSatisfiedBy(Object params) { return !a.isSatisfiedBy(params); } }
这些类就构成了Specification模式的核心部分,下面我们来看一个例子: 先定义一个男人:
public class Men { public String name; // 姓名 public boolean married; // 是否已婚 public int cars; // 拥有车的数量 public int houses; // 拥有房子的数量 public Men(String name,int cars, int houses, boolean married) { this.name = name; this.cars = cars; this.houses = houses; this.married = married; } }
然后定义选男人的几个条件:
// 有车 public class HasCarsSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men)params; return m.cars > 0; } } // 有房 public class HasHousesSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men)params; return m.houses > 0; } } // 已婚 public class MarriedSpecification extends CompositeSpecification { @Override public boolean isSatisfiedBy(Object params) { Men m = (Men)params; return m.married; } }
好,下面有位女嘉宾开始选它心目中的男人了:
Men[] candidates = { new Men("李精英", 1, 1, false), new Men("王老五", 5, 3, true), new Men("赵白领", 0, 1, false), new Men("West_Link", 0, 0, false) }; HasHousesSpecification hasHouse = new HasHousesSpecification(); HasCarsSpecification hasCar = new HasCarsSpecification(); MarriedSpecification married = new MarriedSpecification(); Specification spec = hasHouse.and(hasCar).and(married.not()); for (Men men : candidates) { if(spec.isSatisfiedBy(men)) System.out.println(men.name); }
从Specification spec = hasHouse.and(hasCar).and(married.not())这行代码可以看出这位女嘉宾选择了有车 并且有房的未婚男子,所以打印结果为:李精英。
经过多轮选择,West_Link始终没有被选上!
Tags: 

延伸阅读

最新评论

发表评论