利用Specification形式检索缓存数据

利用Specification模式检索缓存数据

    随着缓存技术的引入,网站前台的检索速度大大提高,随之而来的一个问题是检索。通常的经验都是写几个Sql语句,但是现在不同,我们需要从内存中检索数据。如何解决呢?我的方式是使用Specification模式 。

    Specification模式 把 每一个检索条件转化为对象。我们可以对象进行组合,然后对内存数据进行筛选,这样就可以达到目的。

     为什么要采用Specification,因为Specification可让开发人员专注于 【检索条件】的使用。

     下面给个例子,供大家参考,源代码在附件

    1、年龄规约

public class AgeSpecification extends CompositeSpecification<Member> {
    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<Member> {
    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<T> extends CompositeSpecification<T>{
    private ExpressionCallback<T> ecp;
    public ExpressionSpecification(ExpressionCallback<T> ecp) {
        this.ecp = ecp;
    }
    public boolean isSatisfiedBy(T obj) {
        return ecp.match(obj);
    }
}
public interface ExpressionCallback<T> {
    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<Member> members;

    @Before
    public void setUp() {
        members = new LinkedList<Member>();
        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<Member> s1 = new AgeSpecification(10, 20);
        assertEquals(10, filter(members, s1).size());
    }

    @Test
    public void testFindByName() {
        Specification<Member> s1 = new AgeSpecification(10, 20);
        assertEquals(10, filter(members, s1).size());

    }

    @Test
    public void testFindByAgeAndName() {
        Specification<Member> age = new AgeSpecification(10, 20);
        Specification<Member> name = new NameSpecification("赵");
        Specification<Member> findByAgeAndName = age.and(name);
        assertEquals(1, filter(members, findByAgeAndName).size());
    }

    @Test
    public void testFindByExpression() {
        Specification<Member> expressionSpeci = new ExpressionSpecification<Member>(new ExpressionCallback<Member>() {
            public boolean match(Member obj) {
                return obj.getName().startsWith("赵");
            }
        });
        assertEquals(1, filter(members, expressionSpeci).size());
    }

    private static <T> List<T> filter(Collection<T> list, Specification<T> s) {
        List<T> lists = new LinkedList<T>();
        for (T t : list) {
            if (s.isSatisfiedBy(t)) {
                lists.add(t);
            }
        }
        return lists;
    }

}