本期分享的内容是如何通过接口来实现filter。我们可以叫此模式为filter pattern,过滤器模式。
没错,正如题所说,核心就是接口。
实际需求
抽象需求:
1、过滤器支持and,满足and条件的过滤。
2、过滤器支持or,满足or条件的过滤。
3、过滤器支持=过滤。
具体需求:
1、可以支持在一堆人中过滤出男性。
2、可以支持在一堆人中过滤出女性。
3、可以支持在一堆人中过滤出单身男性。
4、可以支持在一堆人中过滤出单身的人或者是女性。
如果现在有这样的需求摆在你的面前,你会用什么样的方式实现?看到这里你可以停下来仔细想想,或者就此打住然后打开电脑自己写个实现吧。
ifelse实现
你也许会说,我哪管他什么模式,我梭梭就是干:
if(filter eq male){
......
return list;
}
if(filter eq female){
......
return list;
}
if(filter eq (single and male)){
......
return list;
}
if(filter eq (single or female )){
.....
return list;
}
(以上是伪代码)
这不是实现了吗?我哪管他三十七二十一,哪管他什么模式,梭梭就是干。
上图
没错,这样确实已经实现了功能。但你不觉得一直不停的if else并不是那么优雅么。不好意思,我又说出了一个让自己讨厌的词(比如,优雅,解耦。。。哈哈哈)。
如果以后有了更多的条件你还要继续if else。至于不停的if else的不好处你可以去看一些clean code这些书籍有讲,这里就不赘述了。
使用接口重构
好,现在根据“当你遇到if else 的时候,不妨考虑使用接口来做重构”法则对上面的代码进行重构。
现在我们看到了if else。好,我们开始重构吧。
上面分别有4个if块。根据法则,我们应该分别做四个实现,然后每个实现都去遵循一个标准接口。
大体应该是这个样子:
interface Criteria{
List criteria(List list);
}
接口搞好了,然后我们是不是再做四个实现呢?没错。
MaleCriteria impl Criteria{
List criteria(List list){
......
return newlist;
}
}
FemaleCriteria impl Criteria{
List criteria(List list){
......
return newlist;
}
}
AndCriteria impl Criteria{
List criteria(List list){
......
return newlist;
}
}
OrCriteria impl Criteria{
List criteria(List list){
......
return newlist;
}
}
正式实现
按照法则,我们理想的样子应该是上面这样的才对,好,我们现在开始正式的实现吧。
先来搞个接口:
Criteria:
代码语言:javascript复制public interface Criteria {
public List<Person> meetCriteria(List<Person> persons);
}
然后搞四个实现:
MaleCriteria:
代码语言:javascript复制public class MaleCriteria implements Criteria {
public List<Person> meetCriteria(List<Person> persons) {
List<Person> malePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("MALE")){
malePersons.add(person);
}
}
return malePersons;
}
}
FemaleCriteria:
代码语言:javascript复制public class FemaleCriteria implements Criteria {
public List<Person> meetCriteria(List<Person> persons) {
List<Person> femalePersons = new ArrayList<Person>();
for (Person person : persons) {
if(person.getGender().equalsIgnoreCase("FEMALE")){
femalePersons.add(person);
}
}
return femalePersons;
}
}
AndCriteria:
代码语言:javascript复制public class AndCriteria implements Criteria {
private Criteria criteria;
private Criteria otherCriteria;
public AndCriteria(Criteria criteria, Criteria otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
return otherCriteria.meetCriteria(firstCriteriaPersons);
}
}
OrCriteria:
代码语言:javascript复制public class OrCriteria implements Criteria {
private Criteria criteria;
private Criteria otherCriteria;
public OrCriteria(Criteria criteria, Criteria otherCriteria) {
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}
public List<Person> meetCriteria(List<Person> persons) {
List<Person> firstCriteriaItems = criteria.meetCriteria(persons);
List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons);
for (Person person : otherCriteriaItems) {
if(!firstCriteriaItems.contains(person)){
firstCriteriaItems.add(person);
}
}
return firstCriteriaItems;
}
}
Person:
代码语言:javascript复制public class Person {
private String name;
private String gender;
private String maritalStatus;
public Person(String name, String gender, String maritalStatus){
this.name = name;
this.gender = gender;
this.maritalStatus = maritalStatus;
}
public String getName() {
return name;
}
public String getGender() {
return gender;
}
public String getMaritalStatus() {
return maritalStatus;
}
}
好,四个实现ok了。其中and 和 or ,只需要我们把想要传入的条件通过构造函数传入进去然后做实现就可以了。
是不是很神奇。按照法则,我们重构了之前的if else,然后用接口做了更优雅的实现,一切看起来清爽了许多。
你会发现,你通过法则的指引,然后通过重构的手段,最后自己居然写出了一个设计模式。
这就是传说中的filter模式。
综上所述,我们总结一下本文我们使用到的一些关键法则:
1、当你遇到if else 的时候,不妨考虑使用接口来做重构。
2、通过重构来逐步达到想要的效果。
Demo代码:
代码语言:javascript复制public class CriteriaPatternDemo {
public static void main(String[] args) {
List<Person> persons = new ArrayList<Person>();
persons.add(new Person("张儿喜","male", "single"));
persons.add(new Person("赵铁柱", "male", "married"));
persons.add(new Person("翠花", "female", "married"));
persons.add(new Person("兰花", "female", "single"));
persons.add(new Person("建国", "male", "single"));
persons.add(new Person("高栓柱", "male", "single"));
Criteria male = new MaleCriteria();
Criteria female = new FemaleCriteria();
Criteria single = new CriteriaSingle();
Criteria singleMale = new AndCriteria(single, male);
Criteria singleOrFemale = new OrCriteria(single, female);
System.out.println("男: ");
printPersons(male.meetCriteria(persons));
System.out.println("n女: ");
printPersons(female.meetCriteria(persons));
System.out.println("n单身男: ");
printPersons(singleMale.meetCriteria(persons));
System.out.println("n单身或女性: ");
printPersons(singleOrFemale.meetCriteria(persons));
}
public static void printPersons(List<Person> persons){
for (Person person : persons) {
System.out.println("Person : [ Name : " person.getName() ", Gender : " person.getGender() ", Marital Status : " person.getMaritalStatus() " ]");
}
}
}
output:
男:
Person : [ Name : 张儿喜, Gender : male, Marital Status : single ]
Person : [ Name : 赵铁柱, Gender : male, Marital Status : married ]
Person : [ Name : 建国, Gender : male, Marital Status : single ]
Person : [ Name : 高栓柱, Gender : male, Marital Status : single ]
女:
Person : [ Name : 翠花, Gender : female, Marital Status : married ]
Person : [ Name : 兰花, Gender : female, Marital Status : single ]
单身男:
Person : [ Name : 张儿喜, Gender : male, Marital Status : single ]
Person : [ Name : 建国, Gender : male, Marital Status : single ]
Person : [ Name : 高栓柱, Gender : male, Marital Status : single ]
单身或女性:
Person : [ Name : 张儿喜, Gender : male, Marital Status : single ]
Person : [ Name : 兰花, Gender : female, Marital Status : single ]
Person : [ Name : 建国, Gender : male, Marital Status : single ]
Person : [ Name : 高栓柱, Gender : male, Marital Status : single ]
Person : [ Name : 翠花, Gender : female, Marital Status : married ]
哪管什么ifelse,搞个接口,梭梭就是干!