Паттерн Фильтр

Шаблон фильтра или шаблон критериев — это шаблон проектирования, который позволяет разработчикам фильтровать набор объектов с использованием различных критериев и соединять их слабосвязанным способом посредством логических операций. Этот тип шаблонов проектирования относится к структурным шаблонам, поскольку он объединяет несколько критериев для получения единого стандарта.


summary

назначение

Используется для инкапсуляции процесса фильтрации объектов, позволяя динамически фильтровать объекты с использованием различных критериев фильтрации.

Основные решаемые проблемы

Когда набор объектов необходимо фильтровать на основе нескольких различных условий или критериев, шаблон фильтра предоставляет гибкий способ определения этих условий, избегая жесткого кодирования логики фильтрации в клиентском коде.

Сценарий использования

  • Когда коллекцию объектов необходимо фильтровать по различным критериям.
  • Когда логика фильтрации может измениться или когда несколько условий фильтрации необходимо динамически объединить.

Подход к реализации

  • Определите интерфейс фильтра: Создайте интерфейс фильтра и определите метод фильтрации.
  • Реализация конкретных фильтров: реализуйте интерфейс фильтра для каждого критерия фильтрации, инкапсулируя конкретную логику фильтрации.
  • Составной фильтр: позволяет объединять фильтры для формирования сложной логики фильтрации.

Ключевой код

  • Интерфейс фильтра: определите метод фильтрации, напримерmatches()。
  • Класс конкретного фильтра: реализуйте интерфейс фильтра и инкапсулируйте конкретную логику фильтрации.
  • Составной фильтр: реализуйте логику комбинирования фильтров, например логическое И, логическое ИЛИ и т. д.

Пример приложения

  1. Система управления книгами: фильтрация книг по различным критериям, таким как автор, год публикации и категория.
  2. Платформа онлайн-покупок: фильтрация товаров по таким условиям, как цена, бренд и пользовательский рейтинг.

Преимущества

  1. Инкапсуляция: логика фильтрации инкапсулирована в независимых объектах фильтров.
  2. Гибкость: условия фильтрации можно динамически добавлять, изменять или комбинировать.
  3. Расширяемость: новые критерии фильтрации можно легко добавлять без изменения существующего кода.

Недостатки

  • Сложность: по мере увеличения количества условий фильтрации система может стать сложной.
  • Проблемы с производительностью: если комбинация фильтров слишком сложна, производительность может снизиться.

Рекомендации по использованию

  • Когда логика фильтрации может изменяться или объекты необходимо динамически фильтровать по различным критериям, рассмотрите использование паттерна Фильтр.
  • При проектировании убедитесь, что интерфейс фильтра и его реализации остаются согласованными, чтобы облегчить комбинирование и расширение.

Примечания

  • Убедитесь, что логика комбинирования фильтров корректна, чтобы избежать внесения логических ошибок.
  • При реализации учитывайте влияние на производительность, особенно при обработке больших объёмов данных.

summary

Паттерн Фильтр включает следующие основные роли:

  • Интерфейс фильтра (Filter/Criteria): Определяет интерфейс для фильтрации объектов. Этот интерфейс обычно содержит метод для фильтрации объектов по определённым условиям.

  • Конкретные классы фильтров (Concrete Filter/Concrete Criteria): Реализуют интерфейс фильтра, чтобы конкретно определить условия и логику фильтрации объектов.

  • Коллекция объектов (элементы/объекты для фильтрации): Коллекция объектов для фильтрации. Эти объекты обычно являются экземплярами с общими атрибутами, например группа людей, группа товаров и т. д.

  • Клиент: Использует конкретные классы фильтров для фильтрации коллекций объектов. Клиент комбинирует коллекцию объектов с фильтрами, чтобы получить объекты, соответствующие критериям.

Реализация

Мы создадимPersonобъект,Criteriaинтерфейс и классы сущностей, реализующие этот интерфейс, чтобы фильтроватьPersonсписок объектов.CriteriaPatternDemoИспользование классаCriteriaобъектов, фильтрация по различным критериям и их комбинациямPersonсписок объектов.

过滤器模式的 UML 图

Шаг 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); System.out.println("Мужчины: "); printPersons(male.meetCriteria(persons)); System.out.println("\nЖенщины: "); printPersons(female.meetCriteria(persons)); System.out.println("\nОдинокие мужчины: "); printPersons(singleMale.meetCriteria(persons)); System.out.println("\nОдинокие или женщины: "); printPersons(singleOrFemale.meetCriteria(persons)); } public static void printPersons(List<Person> persons){ for (Person person : persons) { System.out.println("Человек : [ Имя : " + person.getName() +", Пол : " + person.getGender() +", Семейное положение : " + person.getMaritalStatus() +" ]"); } } }

Шаг 5

Запустите программу, вывод результата:

Males: 
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Females: 
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]

Single Males: 
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]

Single Or Females: 
Person : [ Name : Robert, Gender : Male, Marital Status : Single ]
Person : [ Name : Diana, Gender : Female, Marital Status : Single ]
Person : [ Name : Mike, Gender : Male, Marital Status : Single ]
Person : [ Name : Bobby, Gender : Male, Marital Status : Single ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Другие расширения