设计模式-用接口来实现filter!梭梭就是干!

本期分享的内容是如何通过接口来实现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:

public interface Criteria {
   public List<Person> meetCriteria(List<Person> persons);
}

然后搞四个实现:

MaleCriteria:

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:

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:

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:

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:

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代码:

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,搞个接口,梭梭就是干!

原文发布于微信公众号 - ImportSource(importsource)

原文发表时间:2017-05-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏诸葛青云的专栏

c语言新手的无奈,几个新手容易犯的错误

如果你是一个c语言新手,你很能试过在写代码的时候看上去明明问题,但是运行的时候就出现了错误。下面的错误你犯过几个?

13810
来自专栏企鹅号快讯

入门新手是用Python2还是Pythony3?不同在哪里?

1. print不再是句子,而是函数,比方本来是 print 'abc' 现在是 print('abc')可是 python2.6+ 能够运用 from __f...

25680
来自专栏LEo的网络日志

广度优先搜索算法(go)

18350
来自专栏TechBox

23种设计模式之工厂三兄弟

关于设计模式,是一个永远说不完的也说不清的话题。毕竟在编程的世界里,没有最好的设计模式,只有最合适的设计模式。甚至有些时候,程序或者问题不到一定的规模,尝试所有...

9210
来自专栏Albert陈凯

函数式编程初探

http://www.ruanyifeng.com/blog/2012/04/functional_programming.html 诞生50多年之后,函数式编...

363100
来自专栏GopherCoder

『No25: 编写可读代码的艺术(2)』

根据:先处理正向逻辑,处理简单的,处理可疑或者有趣的准则,改善如下(仅仅只是调换顺序)

12020
来自专栏IT派

真疯了!Java 9 还没会用,Java 10 就要来了!

2017年8月,JCP执行委员会提出将Java的发布频率改为每六个月一次,随后,Oracle发言人Donald Smith在他的博客中确认了这一消息。该决定将在...

41470
来自专栏数据结构与算法

P2051 [AHOI2009]中国象棋

题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法。大...

28850
来自专栏我的小碗汤

栈:我们能干的事情多着呢

老师:同学们大家好,这些节课我们来讲一下栈。那么什么是栈呢。栈是一种后进先出的线性表,它是按照后进先出的原则存储数据。Last In First Out ,简称...

9630
来自专栏程序员互动联盟

在编程中写的最多的一句代码是啥?

挺有意思的一个问题,作为一个天天写代码的人平时也没怎么太在意这些细节,过滤了几种编程语言,大致总结了几种常用的代码

12630

扫码关注云+社区

领取腾讯云代金券