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

在一个较为复杂的业务流程中,某些条件的满足与否决定了业务逻辑的走向,我们可以把这些条件抽离出来,使得任意个条件以某种关系进行组合,从而灵活地对业务逻辑进行定制。另外,在查询、过滤等应用场合中,我们也可以预定义多个条件,使用这些条件的组合来处理查询逻辑,而不是使用逻辑判断语句来处理,那样只会让代码变得复杂,让脑袋变大。

  在Specification设计模式中,一个条件就是一个specification,多个specification通过串联的方式以某种逻辑关系形成一个组合式的specification。首先看一下整体的UML图:


下面是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始终没有被选上!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值