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{br/>@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{br/>@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{br/>@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架構師羣: 867748702

具有1-5工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加羣。

在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加羣。

如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的可以加羣。


加Java架構師進階交流羣獲取Java工程化、高性能及分佈式、高性能、深入淺出。高架構。
性能調優、Spring,MyBatis,Netty源碼分析和大數據等多個知識點高級進階乾貨的直播免費學習權限
都是大牛帶飛 讓你少走很多的彎路的 羣號是: 867748702對了 小白勿進 最好是有開發經驗

注:加羣要求

1、具有工作經驗的,面對目前流行的技術不知從何下手,需要突破技術瓶頸的可以加。

2、在公司待久了,過得很安逸,但跳槽時面試碰壁。需要在短時間內進修、跳槽拿高薪的可以加。

3、如果沒有工作經驗,但基礎非常紮實,對java工作機制,常用設計思想,常用java開發框架掌握熟練的,可以加。

4、覺得自己很牛B,一般需求都能搞定。但是所學的知識點沒有系統化,很難在技術領域繼續突破的可以加。

5.阿里Java高級大牛直播講解知識點,分享知識,多年工作經驗的梳理和總結,帶着大家全面、科學地建立自己的技術體系和技術認知!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章