随着缓存技术的引入,网站前台的检索速度大大提高,随之而来的一个问题是检索。通常的经验都是写几个Sql语句,但是现在不同,我们需要从内存中检索数据。如何解决呢?我的方式是使用Specification模式 。
Specification模式 把 每一个检索条件转化为对象。我们可以对象进行组合,然后对内存数据进行筛选,这样就可以达到目的。
为什么要采用Specification,因为Specification可让开发人员专注于 【检索条件】的使用。
下面给个例子,供大家参考,源代码在附件
1、年龄规约
public class AgeSpecification extends CompositeSpecification {
private Integer begin;
private Integer end;
public AgeSpecification(Integer begin,Integer end){
if(begin == null) {
this.begin = 0;
}else{
this.begin = begin;
}
if(end == null){
this.end = Integer.MAX_VALUE;
}else{
this.end = end;
}
}
public boolean isSatisfiedBy(Member obj) {
return obj.getAge() >=begin && obj.getAge() <= end;
}
}
2、姓名规约
public class NameSpecification extends CompositeSpecification {
private String words;
public NameSpecification(String s) {
words = s;
}
public boolean isSatisfiedBy(Member obj) {
if(words == null || "".endsWith(words.trim())) return true;
return obj.getName().contains(words);
}
}
3、自定义规约
public class ExpressionSpecification extends CompositeSpecification{
private ExpressionCallback ecp;
public ExpressionSpecification(ExpressionCallback ecp) {
this.ecp = ecp;
}
public boolean isSatisfiedBy(T obj) {
return ecp.match(obj);
}
}
public interface ExpressionCallback {
public boolean match(T obj);
}
4、检索的目标对象
public class Member {
private String name;
private int age;
private String mobile;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Member(String name,int age,String mobile){
this.name =name;
this.age = age;
this.mobile = mobile;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString(){
return "姓名:"+ name +" "+"年龄:" + age +" "+"电话:" + mobile;
}
}
4、测试类
public class TestMemberSearch {
private List members;
@Before
public void setUp() {
members = new LinkedList();
members.add(new Member("张三", 1, "15013243543"));
members.add(new Member("李四", 2, "13013243743"));
members.add(new Member("王武", 3, "18613223243"));
members.add(new Member("找刘", 4, "18112243245"));
members.add(new Member("李八", 5, "13901243647"));
members.add(new Member("星七", 6, "18813223272"));
members.add(new Member("孙虎", 7, "139263246243"));
members.add(new Member("刘琦", 8, "155213243242"));
members.add(new Member("张二天", 9, "150132438755"));
members.add(new Member("欧阳一清", 10, "13701323249"));
members.add(new Member("尧度", 11, "13913243248"));
members.add(new Member("真天", 12, "15213243283"));
members.add(new Member("海星", 13, "15713243283"));
members.add(new Member("范天", 15, "1361323243"));
members.add(new Member("林海", 14, "17013243943"));
members.add(new Member("杨波", 16, "15013243243"));
members.add(new Member("青檬", 17, "15013243243"));
members.add(new Member("赵志", 18, "15013243243"));
members.add(new Member("得人", 19, "15013243243"));
}
@After
public void tearDown() {
members = null;
}
@Test
public void testFindByAgeWhichIsBetween10And20() {
Specification s1 = new AgeSpecification(10, 20);
assertEquals(10, filter(members, s1).size());
}
@Test
public void testFindByName() {
Specification s1 = new AgeSpecification(10, 20);
assertEquals(10, filter(members, s1).size());
}
@Test
public void testFindByAgeAndName() {
Specification age = new AgeSpecification(10, 20);
Specification name = new NameSpecification("赵");
Specification findByAgeAndName = age.and(name);
assertEquals(1, filter(members, findByAgeAndName).size());
}
@Test
public void testFindByExpression() {
Specification expressionSpeci = new ExpressionSpecification(new ExpressionCallback() {
public boolean match(Member obj) {
return obj.getName().startsWith("赵");
}
});
assertEquals(1, filter(members, expressionSpeci).size());
}
private static List filter(Collection list, Specification s) {
List lists = new LinkedList();
for (T t : list) {
if (s.isSatisfiedBy(t)) {
lists.add(t);
}
}
return lists;
}
}