command模式应用总结

最近写了一个分表查询的lib,封装了一些数据结构,可以简化对于分表查询的实现。这个问题主要体现在,对分表进行查询时,原有的单表查询需要进行修改,或者需要在内存中进行处理。修改单表的sql可能导致性能问题,原有的优化可能失效。内存处理则需要一些技巧,搞不好会把太多内容加载到内存中,导致内存被耗光。

我的lib主要使用iterator的模式来解决数据库的读取的问题,每次只读取1000条,放在内存中,当iterator的next移动到缓冲区的尾部时,再次读取1000条,如此可以保证获得所有的数据。当然我们也可以采用双buffer的方式,一个用于提前读取,一个用于输出。不过现在还没这么做。

虽然command模式不是lib的重点,但是这个模式却教会了我一些东西。因为最开始的时候,我并没有想到它。开始,我想的是查询分成几类:

1. 查询结果做union all;

2.查询结果做order by

3. 查询结果做group by

4. 查询结果去重

我发现每个查询都有这样一些参数,一组表名,一个数据库查询的封装,如果需要排序的话,得要一个comparator,如果需要合并的话,得要一个MapReduce。

最初的实现是:

class QueryService{
  Iterator<T> query1(a,b);
  Iterator<T> query2(a,b,c);
  Iterator<T> query3(a,b,d);
}

后来发现参数太多,初始化比较麻烦,于是改成:

X{
a,b
}
X1 extends X{
c
}
X2 extends X{
d
}
class QueryService{
  Iterator<T> query1(X);
  Iterator<T> query2(X1);
  Iterator<T> query3(X2);
}

接着发现,这个设计缺乏扩展性,如果将来需要添加新的查询类型,或者想要换一种实现方式,就得修改整个query service。而且X X1 X2只有属性,太浪费了,没有实现封装的目的。更重要的,各个查询其实如果设置好上下文,调用方法都一样,返回值一样。这不就是command的用法吗。

Cmd{
Iterator run();
}
X implements Cmd{
a,b
}
X1 extends X{
c
}
X2 extends X{
d
}
class QueryService{
  Iterator<T> query(Cmd);
}

这样上面的难题就迎刃而解了。为什么我一开始没想到呢。我想到了不同的种类的查询,过分关注他们的不同点,忽略了查询的共同点。所以以后工作中,一定要先抽取共性,再寻求个性。共性有利于整体考虑,个性有利于细化架构,发现新的机会。

原文地址:https://www.cnblogs.com/alphablox/p/3036808.html