Java计模模式之六

Wesley13
• 阅读 596

前言

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

组合模式

简介

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

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

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

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

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

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

废话不在多说了,下面进行代码的开发。
首先定义一个学生类,有学生姓名和职位属性。
然后在学生类中在添加 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流更方便的进行规则的制定(这一点留在以后再讲)。

过滤器模式的优点:

简单,解耦,使用方便。

过滤器模式的缺点:

好像没有。。。

使用场景:

需要进行筛选的时候。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java中的23种设计模式
java中一共23种设计模式!按照目的来分,设计模式可以分为创建型模式、结构型模式和行为型模式。创建型模式用来处理对象的创建过程;结构型模式用来处理类或者对象的组合;行为型模式用来对类或对象怎样交互和怎样分配职责进行描述。创建型模式用来处理对象的创建过程,主要包含以下5种设计模式:工厂方法模
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
2年前
Java进阶篇设计模式之三
前言在上一篇(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.cnblogs.com%2Fxuwujing%2Fp%2F9363142.html)中我们学习了工厂模式,介绍了简单工厂模式、工厂方法和抽象工厂模式。本篇则介绍设计模式中属于创建型模式的建造者模式和原型模式。
Wesley13 Wesley13
2年前
mysql select将多个字段横向合拼到一个字段
表模式:CREATE TABLE tbl_user (  id int(11) NOT NULL AUTO_INCREMENT,  name varchar(255) DEFAULT NULL,  age int(11) DEFAULT NULL,  PRIMARY KEY (id)
Wesley13 Wesley13
2年前
Java中23种设计模式详解
Java中23种设计模式1\.设计模式31.1创建型模式41.1.1工厂方法41.1.2抽象工厂61.1.3建造者模式101.1.4单态模式131.1.5原型模式151.2结构型模式171.2.1适配器模式171.2.2桥接模式191.2.3组合
Wesley13 Wesley13
2年前
Java Design Patterns
java的设计模式大体上分为三大类:创建型模式(5种):工厂方法模式,抽象工厂模式,单例模式,建造者模式,原型模式。结构型模式(7种):适配器模式,装饰器模式,代理模式,外观模式,桥接模式,组合模式,享元模式。行为型模式(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模
Wesley13 Wesley13
2年前
00_设计模式之语言选择
设计模式之语言选择设计模式简介背景设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。设计模式(Designpattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这