设计模式之过滤器模式

4,349 阅读3分钟

过滤器模式:将多个互不耦合的标准组成连接成一个标准。若没使用过滤器模式的话,我们如果需要根据不同场景将数据根据不同条件去过滤,那么我们需要在一个类中编写一大串的if-else 代码,而且不同场景的逻辑代码耦合在同一个类中,不利于代码维护,以及代码复用。倘若每个场景分别对应一个类,生成标准可以以注册的形式添加,代码复用性更高。

很多框架用到过滤器模式,如tomcat的Filter,Druid数据统计的Filter。感兴趣的同学可以去去看下。

下面是自己编写的用例,加深过滤器模式的理解。

首先创建Filter和FilterChain接口,表明过滤器和过滤链具备哪些功能。

public interface Filter {
   List<FilterDemo> doFilter(List<FilterDemo> filterDemo, FilterChain filterChain);
}

public interface FilterChain {
   List<FilterDemo> doFilter(List<FilterDemo> filterDemos);
}

接着编写Filter的实现类。

根据名字过滤
public class NameFilter implements Filter {
   private static final String TARGET_NAME = "filter";
   @Override
   public List<FilterDemo> doFilter(List<FilterDemo> filterDemo, FilterChain filterChain) {
      FilterDemo temp;
      Iterator<FilterDemo> iterator = filterDemo.iterator();
      while (iterator.hasNext()) {
         temp = iterator.next();
         if (TARGET_NAME.equals(temp.getName())) {
            iterator.remove();
         }
      }
      return filterChain.doFilter(filterDemo);
   }
}

根据性别过滤
public class SexFilter implements Filter {
   private static final String SEX = "man";
   @Override
   public List<FilterDemo> doFilter(List<FilterDemo> filterDemo, FilterChain filterChain) {
      FilterDemo temp;
      Iterator<FilterDemo> iterator = filterDemo.iterator();
      while (iterator.hasNext()) {
         temp = iterator.next();
         if (SEX.equals(temp.getSex())) {
            iterator.remove();
         }
      }
      return filterChain.doFilter(filterDemo);
   }
}

根据年龄过滤
public class AgeFilter implements Filter {
   private static final Integer AGE = 10;
   @Override
   public List<FilterDemo> doFilter(List<FilterDemo> filterDemo, FilterChain filterChain) {
      FilterDemo temp;
      Iterator<FilterDemo> iterator = filterDemo.iterator();
      while (iterator.hasNext()) {
         temp = iterator.next();
         if (AGE.equals(temp.getAge())) {
            iterator.remove();
         }
      }
      return filterChain.doFilter(filterDemo);
   }
}

过滤对象

public class FilterDemo {
   private String name;
   private Integer age;
   private String sex;
   public FilterDemo(String name, Integer age, String sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
   }
    //set() get() toString()  ...
}

最后是过滤链实现

public class FilterChainImp implements FilterChain {
   private List<Filter> filters;//注册的过滤器
   private static int size;//过滤器数
   private static int currentSize = 0;//当前执行的过滤器位置
   public FilterChainImp(List<Filter> filters) {
      this.filters = filters;
      size = filters.size();
   }
   @Override
   public List<FilterDemo> doFilter(List<FilterDemo> filterDemos) {
      if (currentSize < size) {
         filterDemos = filters.get(currentSize++).doFilter(filterDemos, this);
      }
      return filterDemos;
   }
}

最后写个main方法跑下

public class FilterPattern {
   public static void main(String[] args) {
      Filter nameFilter = new NameFilter();
      Filter ageFilter = new AgeFilter();
      Filter sexFilter = new SexFilter();
      List<Filter> filterList = new ArrayList<>(4);
      filterList.add(nameFilter);
      filterList.add(ageFilter);
      filterList.add(sexFilter);
      FilterChain filterChain = new FilterChainImp(filterList);
      FilterDemo demo1 = new FilterDemo("filter", 11, "woman");
      FilterDemo demo2 = new FilterDemo("one", 10, "woman");
      FilterDemo demo3 = new FilterDemo("two", 12, "man");
      FilterDemo demo4 = new FilterDemo("three", 13, "woman");
      List<FilterDemo> demos = new ArrayList<>(4);
      demos.add(demo1);
      demos.add(demo2);
      demos.add(demo3);
      demos.add(demo4);
      List<FilterDemo> result = filterChain.doFilter(demos);
      for (FilterDemo filterDemo : result) {
         System.out.println(filterDemo.toString());
      }
   }
}


最后输出结果:FilterDemo{name='three', age=13, sex='woman'}

通过案例,使用过滤器我们可以根据不同的条件去选择过滤器,过滤器也可以各自组合,不必相同的代码不断被复制。


个人见解:过滤器模式核心逻辑在于调用过滤器时,过滤链(FilterChain)当做参数传入,当走完一个过滤器后继续调用过滤链的过滤方法执行下一个过滤器,直至过滤器全都走完。

看完当前案例回头再去tomcat的过滤器,相信能帮助你更好的理解它的工作机制。


                                                        

                                                     (扫码关注公众号)



注:基于水平限制,文档只是对于自己的提升,有出入请指教。(未经授权禁转)