我们在使用mysql的时候 经常会写where语句 比如 where (age>18 and name="张三")or age >2 .那么这种是怎么实现的呢?这里我们用一个设计模式 :specification
我们首先定义一个接口:
public interface Specification {
public boolean isSatisfiedBy(T t);
}
isSatisfiedBy() 这个方法是用来检测是否满足我们的条件。后面的所有操作都是基于这个方法来设计,继续定义一个基类:
public abstract class AbstractSpecification implements Specification {
public abstract boolean isSatisfiedBy(T t);
public AbstractSpecification or(Specification s) {
return new OrSpecification(this,s);
}
public AbstractSpecification and(Specification s) {
return new AndSpecification(this,s);
}
public AbstractSpecification not() {
return new NotSpecification(this);
}
}
这个基类里实现了specification 接口 提供了一个抽象方法 isSatisfiedBy()给子类覆盖
添加三个子类 and or not
public class AndSpecification extends AbstractSpecification {
private Set> set = new HashSet>();
public AndSpecification(Specification a, Specification b) {
set.add(a);
set.add(b);
}
public boolean isSatisfiedBy(T t) {
for( Specification s : set ) {
if( !s.isSatisfiedBy(t) ) {
return false;
}
}
return true;
}
@Override
public AbstractSpecification and(Specification s) {
set.add(s);
return this;
}
}
public class NotSpecification extends AbstractSpecification {
private Specification spec;
public NotSpecification(Specification s) {
this.spec=s;
}
@Override
public boolean isSatisfiedBy(T t) {
return !spec.isSatisfiedBy(t);
}
}
public class OrSpecification extends AbstractSpecification {
private Set> set = new HashSet>();
public OrSpecification(Specification a, Specification b) {
set.add(a);
set.add(b);
}
public boolean isSatisfiedBy(T t) {
for( Specification s : set ) {
if( s.isSatisfiedBy(t) ) {
return true;
}
}
return false;
}
@Override
public AbstractSpecification or(Specification s) {
set.add(s);
return this;
}
}
基本的框架已经达成了 ,现在实现一个 年龄大于num的类:
public class AgeMoreThanSpecification extends AbstractSpecification {
private int age;
public AgeMoreThanSpecification (int age) {
super();
this.age= age;
}
public boolean isSatisfiedBy(People t) {
return t.age>age;
}
}
继续加一个name 等于 xxx的类:
public class NameSpecification extends AbstractSpecification {
private String name;
public ToyTypeNameSpecification(String name) {
super();
this.name = name;
}
@Override
public boolean isSatisfiedBy(People t) {
return t.getName().equals(name);
}
}
ok 返回看开始说的那个sql 条件 where (age>18 and name="张三")or age >2
我可以构造一个people list 来找这些满足的条件
//此处为伪代码
People p=new People("张三",19);
People p2=new People("张三1",1);
People p3=new People("张三2",1);
People p4=new People("张三3",14);
List.add(p);
List.add(p2);
List.add(p3);
List.add(p4);
Specification specification=new OrSpecification(new AndSpecification(new AgeMoreThanSpecification(18),new NameSpecification("张三")),new AgeMoreThanSpecification(2));
for l:list
if(specification.isSatisfiedBy(l)){
//find 2 item People p4=new People("张三3",14); People p=new People("张三",19);
}
优点代码的实现全部隐藏,只暴露过程。 缺点就是类的数量比较多。添加一个条件就是一个子类。