Java進階篇設計模式之六 ----- 組合模式和過濾器模式

来源:https://www.cnblogs.com/xuwujing/archive/2018/09/11/9630850.html
-Advertisement-
Play Games

前言 在 "上一篇" 中我們學習了結構型模式的外觀模式和裝飾器模式。本篇則來學習下組合模式和過濾器模式。 組合模式 簡介 組合模式是用於把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬於結構型模式,它創建了對象組的樹形結構。 簡單來說 ...


前言

上一篇中我們學習了結構型模式的外觀模式和裝飾器模式。本篇則來學習下組合模式和過濾器模式。

組合模式

簡介

組合模式是用於把一組相似的對象當作一個單一的對象。組合模式依據樹形結構來組合對象,用來表示部分以及整體層次。這種類型的設計模式屬於結構型模式,它創建了對象組的樹形結構。

簡單來說的話,就是根據樹形結構把相似的對象進行組合,然後表示該部分是用來做啥的。在<大話設計模式>中有個很形象的例子,就是電腦中的 文件系統

文件系統由目錄和文件組成。每個目錄都可以裝內容。目錄的內容可以是文件,也可以是目錄。按照這種方式,電腦的文件系統就是以遞歸結構來組織的。

當然,這裡我們也可以使用一個簡單的示例來對組合模式進行講解。

在學校中,有很多學生,但是這些學生中又有不同的身份,有的學生是學生會主席,有的是學生會委員,有的是班長,有的是體育委員等等, 當然大部分都是普通的學生,並沒有擔當其它的職位。這時我們就可以使用組合模式來進行組合。

按照管理層來看,學生職位中最大的是學生會主席,學生會主席下有學生會委員,然後學生會委員又管理著普通的學生,他們之間相互獨立,可以成為一個部分,也可以最終成為一個整體。可以說非常符合組合模式中的樹形結構以表示‘部分-整體’的層次結構

廢話不在多說了,下麵進行代碼的開發。
首先定義一個學生類,有學生姓名和職位屬性。
然後在學生類中在添加 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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • c/c++ 多維數組和指針 知識點 1,初始化多維數組,對應代碼里的test1 2,遍歷多維數組,除了最內層迴圈外,其他所有層都必須是引用類型,對應代碼里的test2 3,指針和多維數組 ,對應代碼里的test3 c++ include using namespace std; int main() ...
  • c/c++ 數組和指針 知識點 1,數組就是指針,對應代碼里的test1 2,用auto聲明,得到的是指針,對應代碼里的test2 3,用decltype聲明,得到的不是指針 ,對應代碼里的test3 4,用指針模擬end ,對應代碼里的test4 5,標準庫函數std::begin,std::en ...
  • 在java中,可以根據Class類的對象,知道某個類(介面)的一些屬性(成員 ,方法,註釋,註解)等。由於最近的工作中用到了這些,其中需要在代碼中格局反射知道某些類的方法,查看文檔的時候,看到了getMethods()和getDeclaredMethods()的差異。雖然兩者都能實現目的,但個人覺得 ...
  • 給你一個字元串,比如‘abc’,請列印出該字元串的所有排列組合: 以‘abc’為例,輸出的結果應該是:'abc', 'acb', 'bac', 'bca', 'cab', 'cba' 請用python代碼編碼實現: ...
  • JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式,它使得人們很容易的進行閱讀和編寫。同時也方便了機器進行解析和生成。JSON在數據交換中起到了一個載體的作用,承載著相互傳遞的數據。JSON適用於進行數據交互的場景,比如網站前臺與後臺之間的數據交互。 jso ...
  • 用來計算連續變數的發生率,說的很抽象,簡單說就是單獨拿出來沒什麼太大用,但並不是說這個沒什麼用,相反這個太重要了,這玩意能讓你看清世界的真相 先看個圖,像這樣的線性就是正太分佈 這是一個標準的正態分佈 正太分佈有4個特點 呈鐘形分佈,是對稱的 分佈的集中趨勢(均值、中位數、眾數)都一樣 中間最高的部 ...
  • 今天學習的內容是:JDBC http://www.cnblogs.com/centor/p/6142775.html 首先我們把這部分內容仔細閱讀然後複製粘貼到下麵 以mysql為例 工具:eclipse MySQL5.6 MySQL連接驅動:mysql-connector-java-5.1.27. ...
  • 給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出null 1.找鏈表倒數第k個結點,輸入一個鏈表,輸出該鏈表中倒數第k個結點。第一個指針走(k-1)步,到達第k個節點,兩個指針同時往後移動,當第一個結點到達末尾的時候,第二個結點所在位置就是倒數第k個節點了 2.原理有點像上面的,定義... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...