過濾器模式
過濾器模式(Filter Pattern)或標準模式(Criteria Pattern)是一種設計模式,這種模式允許開發人員使用不同的標準來過濾一組對象,通過邏輯運算以解耦的方式把它們連接起來。這種類型的設計模式屬于結構型模式,它結合多個標準來獲得單一標準。 雙龍物流
概要
意圖
用于將對象的篩選過程封裝起來,允許使用不同的篩選標準動態地篩選對象。
主要解決的問題
當需要根據多個不同的條件或標準來篩選一組對象時,過濾器模式提供了一種靈活的方式來定義這些條件,避免在客戶端代碼中硬編碼篩選邏輯。
使用場景
- 當對象集合需要根據不同的標準進行篩選時。
- 當篩選邏輯可能變化,或者需要動態地組合多個篩選條件時。
實現方式
- 定義篩選接口:創建一個篩選接口,定義一個篩選方法。
- 實現具體篩選器:為每個篩選標準實現篩選接口,封裝具體的篩選邏輯。
- 組合篩選器:允許篩選器之間進行組合,形成復雜的篩選邏輯。
關鍵代碼
- 篩選接口:定義篩選方法,如
matches()。 - 具體篩選器類:實現篩選接口,封裝具體的篩選邏輯。
- 組合篩選器:實現篩選器的組合邏輯,如邏輯與(AND)、邏輯或(OR)等。
應用實例
- 圖書管理系統:根據作者、出版年份、類別等不同標準篩選圖書。
- 在線購物平臺:根據價格、品牌、用戶評分等條件篩選商品。
優點
- 封裝性:篩選邏輯被封裝在獨立的篩選器對象中。
- 靈活性:可以動態地添加、修改或組合篩選條件。
- 可擴展性:容易添加新的篩選標準,無需修改現有代碼。
缺點
- 復雜性:隨著篩選條件的增加,系統可能變得復雜。
- 性能問題:如果篩選器組合過于復雜,可能會影響性能。
使用建議
- 當篩選邏輯可能變化或需要根據不同標準動態篩選對象時,考慮使用過濾器模式。
- 在設計時,確保篩選器的接口和實現保持一致,以便于組合和擴展。
注意事項
- 確保篩選器的組合邏輯正確無誤,避免引入邏輯錯誤。
- 在實現時,考慮性能影響,特別是在處理大量數據時。
概要
過濾器模式包含以下幾個主要角色:
-
過濾器接口(Filter/Criteria):定義一個接口,用于篩選對象。該接口通常包含一個方法,用于根據特定條件過濾對象。
-
具體過濾器類(Concrete Filter/Concrete Criteria):實現過濾器接口,具體定義篩選對象的條件和邏輯。
-
對象集合(Items/Objects to be filtered):要被過濾的對象集合。這些對象通常是具有共同屬性的實例,例如一組人、一組產品等。
-
客戶端(Client):使用具體過濾器類來篩選對象集合。客戶端將對象集合和過濾器結合起來,以獲得符合條件的對象。
實現
我們將創建一個 Person 對象、Criteria 接口和實現了該接口的實體類,來過濾 Person 對象的列表。CriteriaPatternDemo 類使用 Criteria 對象,基于各種標準和它們的結合來過濾 Person 對象的列表。
步驟 1
創建一個類,在該類上應用標準。
Person.java
public class Person { private String name; private String gender; private String maritalStatus; public Person(String name,String gender,String maritalStatus){ this.name = name; this.gender = gender; this.maritalStatus = maritalStatus; } public String getName() { return name; } public String getGender() { return gender; } public String getMaritalStatus() { return maritalStatus; } }
步驟 2
為標準(Criteria)創建一個接口。
Criteria.java
import java.util.List; public interface Criteria { public List<Person> meetCriteria(List<Person> persons); }
步驟 3
創建實現了 Criteria 接口的實體類。
CriteriaMale.java
import java.util.ArrayList; import java.util.List; public class CriteriaMale implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> malePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getGender().equalsIgnoreCase("MALE")){ malePersons.add(person); } } return malePersons; } }
CriteriaFemale.java
import java.util.ArrayList; import java.util.List; public class CriteriaFemale implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> femalePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getGender().equalsIgnoreCase("FEMALE")){ femalePersons.add(person); } } return femalePersons; } }
CriteriaSingle.java
import java.util.ArrayList; import java.util.List; public class CriteriaSingle implements Criteria { @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> singlePersons = new ArrayList<Person>(); for (Person person : persons) { if(person.getMaritalStatus().equalsIgnoreCase("SINGLE")){ singlePersons.add(person); } } return singlePersons; } }
AndCriteria.java
import java.util.List; public class AndCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public AndCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> firstCriteriaPersons = criteria.meetCriteria(persons); return otherCriteria.meetCriteria(firstCriteriaPersons); } }
OrCriteria.java
import java.util.List; public class OrCriteria implements Criteria { private Criteria criteria; private Criteria otherCriteria; public OrCriteria(Criteria criteria, Criteria otherCriteria) { this.criteria = criteria; this.otherCriteria = otherCriteria; } @Override public List<Person> meetCriteria(List<Person> persons) { List<Person> firstCriteriaItems = criteria.meetCriteria(persons); List<Person> otherCriteriaItems = otherCriteria.meetCriteria(persons); for (Person person : otherCriteriaItems) { if(!firstCriteriaItems.contains(person)){ firstCriteriaItems.add(person); } } return firstCriteriaItems; } }
步驟4
使用不同的標準(Criteria)和它們的結合來過濾 Person 對象的列表。
CriteriaPatternDemo.java
import java.util.ArrayList; import java.util.List; public class CriteriaPatternDemo { public static void main(String[] args) { List<Person> persons = new ArrayList<Person>(); persons.add(new Person("Robert","Male", "Single")); persons.add(new Person("John","Male", "Married")); persons.add(new Person("Laura","Female", "Married")); persons.add(new Person("Diana","Female", "Single")); persons.add(new Person("Mike","Male", "Single")); persons.add(new Person("Bobby","Male", "Single")); Criteria male = new CriteriaMale(); Criteria female = new CriteriaFemale(); Criteria single = new CriteriaSingle(); Criteria singleMale = new AndCriteria(single, male); Criteria singleOrFemale = new OrCriteria(single, female)
