Java计模模式之六 ----- 组合模式和过滤器模式
前言
在上一篇中我们学习了结构型模式的外观模式和装饰器模式。本篇则来学习下组合模式和过滤器模式。
组合模式
简介
组合模式是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
简单来说的话,就是根据树形结构把相似的对象进行组合,然后表示该部分是用来做啥的。在<大话设计模式>中有个很形象的例子,就是电脑中的 文件系统。
文件系统由目录和文件组成。每个目录都可以装内容。目录的内容可以是文件,也可以是目录。按照这种方式,计算机的文件系统就是以递归结构来组织的。
当然,这里我们也可以使用一个简单的示例来对组合模式进行讲解。
在学校中,有很多学生,但是这些学生中又有不同的身份,有的学生是学生会主席,有的是学生会委员,有的是班长,有的是体育委员等等, 当然大部分都是普通的学生,并没有担当其它的职位。这时我们就可以使用组合模式来进行组合。
按照管理层来看,学生职位中最大的是学生会主席,学生会主席下有学生会委员,然后学生会委员又管理着普通的学生,他们之间相互独立,可以成为一个部分,也可以最终成为一个整体。可以说非常符合组合模式中的树形结构以表示‘部分-整体’的层次结构
。
废话不在多说了,下面进行代码的开发。
首先定义一个学生类,有学生姓名和职位属性。
然后在学生类中在添加 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流更方便的进行规则的制定(这一点留在以后再讲)。
过滤器模式的优点:
简单,解耦,使用方便。
过滤器模式的缺点:
好像没有。。。
使用场景:
需要进行筛选的时候。
Java计模模式之六 ----- 组合模式和过滤器模式的更多相关文章
- Java进阶篇设计模式之六 ----- 组合模式和过滤器模式
前言 在上一篇中我们学习了结构型模式的外观模式和装饰器模式.本篇则来学习下组合模式和过滤器模式. 组合模式 简介 组合模式是用于把一组相似的对象当作一个单一的对象.组合模式依据树形结构来组合对象,用来 ...
- Java函数接口实现函数组合及装饰器模式
摘要: 通过求解 (sinx)^2 + (cosx)^2 = 1 的若干写法,逐步展示了如何从过程式的写法转变到函数式的写法,并说明了编写"[接受函数参数]并返回[能够接受函数参数的函数]的 ...
- java:Filter、Listener 自定义拦截器和过滤器应用
一,Filter FilterEncoding 过滤器,统一设置servlet的编码格式. package com.dkt.filter; import java.io.IOException; im ...
- 设计模式的征途—9.组合(Composite)模式
树形结构在软件中随处可见,比如操作系统中的目录结构,公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题.组合模式通过一种巧妙的设计方案来使得用户可以一致性地处理整个树形 ...
- 设计模式之组合(compose)模式
树形结构在软件中随处可见,比如操作系统中的目录结构,公司组织结构等等,如何运用面向对象的方式来处理这种树形结构是组合模式需要解决的问题.组合模式通过一种巧妙的设计方案来使得用户可以一致性地处理整个树形 ...
- Java设计模式(8)组合模式(Composite模式)
Composite定义:将对象以树形结构组织起来,以达成“部分-整体” 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Composite就应该想到树 ...
- Java描述设计模式(10):组合模式
本文源码:GitHub·点这里 || GitEE·点这里 一.生活场景 1.文件系统 下图是常见的计算机文件系统的一部分. 文件系统是一个树结构,树上长有节点.树的节点有两种: 树枝节点 即文件夹,有 ...
- 设计模式GOF23(结构型模式:代理模式,适配模式,桥接模式,组合模式,装饰模式,外观模式,享元模式)
结构型模式: – 分类: • 适配器模式.代理模式.桥接模式.装饰模式.组合模式.外观模式.享元模式 – 核心作用:是从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题. 结构 ...
- OOAD-设计模式(四)结构型模式之适配器、装饰器、代理模式
前言 前面我们学习了创建型设计模式,其中有5中,个人感觉比较重要的是工厂方法模式.单例模式.原型模式.接下来我将分享的是结构型模式! 一.适配器模式 1.1.适配器模式概述 适配器模式(Adapter ...
随机推荐
- MySQL分布式jdbc连接
参考文档: https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-multi-host-connections.html 服务器故障转移 连 ...
- Linux下网络文件系统NFS服务搭建易错点总结
一.环境准备: 1 [root@czh ~]# cat /etc/redhat-release 2 CentOS release 6.7 (Final) 3 [root@czh ~]# uname - ...
- 使用shell脚本来自动化处理我们的工作,解放双手
Shell脚本介绍 1.Shell脚本,就是利用Shell的命令解释的功能,对一个纯文本的文件进行解析,然后执行这些功能,也可以说Shell脚本就是一系列命令的集合. 2.Shell可以直接使用在wi ...
- Hive基础之绪论
我本人大概是从2013年12月份开始接触Hadoop,因为公司当时要开始处理一些数据量比较大的数据,现有的通过程序去统计数据的方式在效率方面渐渐不能满足业务需求,所以便开始了Hadoop技术的探索,即 ...
- 将代码从 spark 1.x 移植到 spark 2.x
1. SparkSession sparkSession可以视为sqlContext和hiveContext以及StreamingContext的结合体,这些Context的API都可以通过spark ...
- SpringCloud(二)Eureka集群与Feign
两个Eureka 上一篇是两个服务像一个Eureka注册,如果Eureka宕掉了就不好了,现在来搭建两个Eureka,两个服务分别像其注册.两个Eureka都用本机来模拟,用两个端口号来表示. 首先修 ...
- Servlet—Cookie(显示用户上次访问时间、显示商品浏览历史)
1 . 什么是会话? 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 1.1 会话过程中要解决的一些问题? 每个用户在使用浏览器 ...
- 每个JavaScript工程师都应懂的33个概念
摘要: 基础很重要啊! 原文:33 concepts every JavaScript developer should know 译文:每个 JavaScript 工程师都应懂的33个概念 作者:s ...
- canvas-arc.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Docker 搭建 ELK 收集并展示 tomcat 日志
架构 前端展示 --> 索引搜索 <-- 日志提取及过滤 --> 日志缓存 <-- 日志收集 Kibana --> Elastash <-- Logstash -- ...