前言

上一篇中我们学习了结构型模式的外观模式和装饰器模式。本篇则来学习下组合模式和过滤器模式。

组合模式

简介

组合模式是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

简单来说的话,就是根据树形结构把相似的对象进行组合,然后表示该部分是用来做啥的。在<大话设计模式>中有个很形象的例子,就是电脑中的 文件系统

文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。

当然,这里我们也可以使用一个简单的示例来对组合模式进行讲解。

在学校中,有很多学生,但是这些学生中又有不同的身份,有的学生是学生会主席,有的是学生会委员,有的是班长,有的是体育委员等等, 当然大部分都是普通的学生,并没有担当其它的职位。这时我们就可以使用组合模式来进行组合。

按照管理层来看,学生职位中最大的是学生会主席,学生会主席下有学生会委员,然后学生会委员又管理着普通的学生,他们之间相互独立,可以成为一个部分,也可以最终成为一个整体。可以说非常符合组合模式中的树形结构以表示‘部分-整体’的层次结构

废话不在多说了,下面进行代码的开发。

首先定义一个学生类,有学生姓名和职位属性。

然后在学生类中在添加 add()、remove()、get()方法,最后进行层级调用。

代码示例:

class Student{
private String name; private String position; private List<Student> students; public Student(String name, String position) {
this.name = name;
this.position = position;
students=new ArrayList<Student>();
} public void add(Student student){
students.add(student);
} public void remove(Student student){
students.remove(student);
} public List<Student> get(){
return students;
} @Override
public String toString() {
return "Student [name=" + name + ", position=" + position + "]";
}
} public class CompositeTest { public static void main(String[] args) { Student studentLeader=new Student("小明","学生会主席"); Student committeeMember=new Student("小刚","学生会委员"); Student student=new Student("小红","学生"); committeeMember.add(student);
studentLeader.add(committeeMember); System.out.println("-"+studentLeader);
studentLeader.get().forEach(sl->{
System.out.println("--"+sl);
sl.get().forEach(cm->{
System.out.println("---"+cm);
});
});
}
}

输出结果:

	-Student [name=小明, position=学生会主席]
--Student [name=小刚, position=学生会委员]
---Student [name=小红, position=学生]

在上述示例中,我们添加了三个学生(更多也一样,主要是思路),在学校中分别扮演 学生会主席、学生会委员以及学生。其中学生会主席管理着学生会委员,学生会委员管理着学生,他们之间属于层级关系,一层层的包含。在这之中,我们也发现一点,其实组合模式就是把某个对象去包含另一个对象,然后通过组合的方式来进行一些布局。

组合模式的优点:

高层模块调用较为简单,增加某个节点方便。

组合模式的缺点:

因为其子节点的声明都是实现类,而不是接口,违反了依赖倒置原则。

使用场景:

可以表示为 ‘部分-整体’的层级结构。

过滤器模式

简介

过滤器模式允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来。这种类型的设计模式属于结构型模式,它结合多个标准来获得单一标准。

简单的来说该模式的功能就是如其名,做一个过滤的作用。我们在一般在进行后台接口开发的时候,也会根据过滤掉一些请求。其实过滤器模式主要实现也是这种功能,废话不多说,开始用代码进行相应的说明。

这里依旧用学生来进行讲解,学校的学生中有男生和女生,学校又有不同的年级,这时我们相统计下学生的相关信息,就可以使用过滤器模式来进行分组了。比如,统计该学校有多少男生,一年级的女生有多少,三年级的学生或者女生有多少之类等等。

代码示例:

由于代码有点多,这里就分开进行讲解。

首先定义一个实体类,有姓名、性别、年级这三个属性。

class Student{
private String name;
private String gender;
private Integer grade;
public Student(String name, String gender, Integer grade) {
super();
this.name = name;
this.gender = gender;
this.grade = grade;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getGender() {
return gender;
} public void setGender(String gender) {
this.gender = gender;
} public Integer getGrade() {
return grade;
} public void setGrade(Integer grade) {
this.grade = grade;
} @Override
public String toString() {
return "Student [name=" + name + ", gender=" + gender + ", grade=" + grade + "]";
}
}

然后再定义一个公用的接口,指定实现的方法。

interface FilterinGrule {
List<Student> filter(List<Student> students);
}

然后再实现该接口,制定不同的过滤规则。这里主要是三种规则,普通的过滤,且过滤,或过滤。

具体实现的方法如下:

class MaleStudents implements FilterinGrule{
@Override
public List<Student> filter(List<Student> students) {
List<Student> maleStudents = new ArrayList<Student>();
students.forEach(student->{
if(student.getGender().equalsIgnoreCase("male")){
maleStudents.add(student);
}
});
return maleStudents;
}
} class FemaleStudents implements FilterinGrule{
@Override
public List<Student> filter(List<Student> students) {
List<Student> femaleStudents = new ArrayList<Student>();
students.forEach(student->{
if(student.getGender().equalsIgnoreCase("female")){
femaleStudents.add(student);
}
});
return femaleStudents;
}
} class SecondGrade implements FilterinGrule{
@Override
public List<Student> filter(List<Student> students) {
List<Student> secondGradeStudents = new ArrayList<Student>();
students.forEach(student->{
if(student.getGrade() == 2){
secondGradeStudents.add(student);
}
}); return secondGradeStudents;
}
} class And implements FilterinGrule{
private FilterinGrule filter;
private FilterinGrule filter2; public And(FilterinGrule filter,FilterinGrule filter2) {
this.filter=filter;
this.filter2=filter2;
} @Override
public List<Student> filter(List<Student> students) {
List<Student> students2=filter.filter(students);
return filter2.filter(students2);
}
} class Or implements FilterinGrule{
private FilterinGrule filter;
private FilterinGrule filter2; public Or(FilterinGrule filter,FilterinGrule filter2) {
this.filter=filter;
this.filter2=filter2;
} @Override
public List<Student> filter(List<Student> students) {
List<Student> students1=filter.filter(students);
List<Student> students2=filter2.filter(students);
students2.forEach(student->{
if(!students1.contains(student)){
students1.add(student);
}
});
return students1;
}
}

最后再来进行调用测试,添加一些学生,并且指定性别以及班级。然后根据不同的条件来进行过滤。

public class FilterTest {

	public static void main(String[] args) {
List<Student> list=new ArrayList<Student>();
list.add(new Student("小明", "male", 1));
list.add(new Student("小红", "female", 2));
list.add(new Student("小刚", "male", 2));
list.add(new Student("小霞", "female", 3));
list.add(new Student("小智", "male", 3));
list.add(new Student("虚无境", "male", 1)); FilterinGrule male = new MaleStudents();
FilterinGrule female = new FemaleStudents();
FilterinGrule secondGrade = new SecondGrade();
FilterinGrule secondGradeMale = new And(secondGrade, male);
FilterinGrule secondGradeOrFemale = new Or(secondGrade, female); System.out.println("男生:"+male.filter(list));
System.out.println("女生:"+female.filter(list));
System.out.println("二年级学生:"+secondGrade.filter(list));
System.out.println("二年级男生:"+secondGradeMale.filter(list));
System.out.println("二年级的学生或女生:"+secondGradeOrFemale.filter(list));
}
}

输出结果:

男生:[Student [name=小明, gender=male, grade=1], Student [name=小刚, gender=male, grade=2], Student [name=小智, gender=male, grade=3], Student [name=虚无境, gender=male, grade=1]]
女生:[Student [name=小红, gender=female, grade=2], Student [name=小霞, gender=female, grade=3]]
二年级学生:[Student [name=小红, gender=female, grade=2], Student [name=小刚, gender=male, grade=2]]
二年级男生:[Student [name=小刚, gender=male, grade=2]]
二年级的学生或女生:[Student [name=小红, gender=female, grade=2], Student [name=小刚, gender=male, grade=2], Student [name=小霞, gender=female, grade=3]]

通过上述示例,我们发现过滤器模式其实很简单,制定过滤规则,然后再根据制定的标准来进行过滤,得到符合条件的数据。过滤器模式虽然简单,但是在构建过滤规则的时候,有点繁琐,不过在jdk1.8之后,我们可以使用stream流更方便的进行规则的制定(这一点留在以后再讲)。

过滤器模式的优点:

简单,解耦,使用方便。

过滤器模式的缺点:

好像没有。。。

使用场景:

需要进行筛选的时候。

其它

音乐推荐

其实边听音乐便看博客很享受的_

原创不易,如果感觉不错,希望给个推荐!您的支持是我写作的最大动力!

版权声明:

作者:虚无境

博客园出处:http://www.cnblogs.com/xuwujing

CSDN出处:http://blog.csdn.net/qazwsxpcm 

个人博客出处:http://www.panchengming.com

Java进阶篇设计模式之六 ----- 组合模式和过滤器模式的更多相关文章

  1. Java进阶篇设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  2. Java计模模式之六 ----- 组合模式和过滤器模式

    前言 在上一篇中我们学习了结构型模式的外观模式和装饰器模式.本篇则来学习下组合模式和过滤器模式. 组合模式 简介 组合模式是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来 ...

  3. Java进阶篇 设计模式之十四 ----- 总结篇

    前言 本篇是讲述之前学习设计模式的一个总结篇,其目的是为了对这些设计模式的进行一个提炼总结,能够通过查看看此篇就可以理解一些设计模式的核心思想. 设计模式简介 什么是设计模式 设计模式是一套被反复使用 ...

  4. Java进阶篇设计模式之八 ----- 责任链模式和命令模式

    前言 在上一篇中我们学习了结构型模式的享元模式和代理模式.本篇则来学习下行为型模式的两个模式, 责任链模式(Chain of Responsibility Pattern)和命令模式(Command ...

  5. Java进阶篇设计模式之三 ----- 建造者模式和原型模式

    前言 在上一篇中我们学习了工厂模式,介绍了简单工厂模式.工厂方法和抽象工厂模式.本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式. 建造者模式 简介 建造者模式是属于创建型模式.建造者模式使用 ...

  6. Java进阶篇设计模式之十三 ---- 观察者模式和空对象模式

    前言 在上一篇中我们学习了行为型模式的备忘录模式(Memento Pattern)和状态模式(Memento Pattern).本篇则来学习下行为型模式的最后两个模式,观察者模式(Observer P ...

  7. Java进阶篇设计模式之十一 ---- 策略模式和模板方法模式

    前言 在上一篇中我们学习了行为型模式的访问者模式(Visitor Pattern)和中介者模式(Mediator Pattern).本篇则来学习下行为型模式的两个模式,策略模式(Strategy Pa ...

  8. Java进阶篇设计模式之十 ---- 访问者模式和中介者模式

    前言 在上一篇中我们学习了行为型模式的解释器模式(Interpreter Pattern)和迭代器模式(Iterator Pattern).本篇则来学习下行为型模式的两个模式,访问者模式(Visito ...

  9. Java进阶篇设计模式之九----- 解释器模式和迭代器模式

    前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...

随机推荐

  1. iframe 背景透明设置--兼容IE

    iframe标签添加: allowTransparency="true"属性. 子文件body背景设置透明: background-color: transparent;.

  2. 用Django做一个团队介绍

    所用工具 Pycharm 社区版 Django 2.x Python 3.6.4 总目录 settings中的设置 总的路由设置 templates中的index.html文件 <!DOCTYP ...

  3. 学习AD、DA的体会

    AD转换器的转换是指模拟信号输入转化为数字信号输出,而DA转换器是把数字信号转换为模拟信号,在ADC0832.TLC549和TLC5615程序设计中,通过使用中断服务函数每0.5s对ADC0832进行 ...

  4. 什么是分布式锁及正确使用redis实现分布式锁

    分布式锁 分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性. 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁 ...

  5. 盒子模型、IFC、BFC和Collapsing margins

    前言 盒子模型作为CSS基础中的基础,曾一度以为掌握了IE和W3C标准下的块级盒子模型即可,但近日在学习行级盒子模型时发现原来当初是如此幼稚可笑.本文尝试全面叙述块级.行级盒子模型的特性.作为近日学习 ...

  6. 使用非阻塞ServerSocketChannel、SocketChannel代替ServerSocket和Socket

    http://blog.csdn.net/timliang18601860/article/details/7104485

  7. capwap学习笔记——初识capwap(三)(下)

    2.5.6.25 Image Data to Reset WTP下载image后重启,重新设置DTLS连接 ¢  WTP: ü   当image的下载完成,或者ImageDataStartTimer定 ...

  8. spring Cloud 域名映射 ip地址实现

    spring.cloud.inetutils.preferredNetworks[0]=^192\.168 eureka.instance.prefer-ip-address=true

  9. js算法初窥03(简单搜索及去重算法)

    前面我们了解了一些常用的排序算法,那么这篇文章我们来看看搜索算法的一些简单实现,我们先来介绍一个我们在实际工作中一定用到过的搜索算法--顺序搜索. 1.顺序搜索 其实顺序搜索十分简单,我们还是以第一篇 ...

  10. 在腾讯云(windows)上搭建node.js服务器

    1:安装Node.js 使用MSI文件,并按照提示安装node.js,默认情况下,安装程序将 Node.js 发行到 C:\Program Files\nodejs. 但这里我们需要修改安装路径到:D ...