Showing posts with label Criteria Pattern. Show all posts
Showing posts with label Criteria Pattern. Show all posts

Wednesday, 9 October 2013

Filter or Criteria Design Pattern - KeyPoints

Master Core Java Architecture & Design Patterns!

Subscribe to Ram N Java for clean code principles, GoF design patterns, and step-by-step software engineering tutorials!

🔔 Subscribe to Ram N Java

Core Summary of the Filter / Criteria Pattern

The Filter Design Pattern (also widely known as the Criteria Design Pattern) is a structural pattern designed to filter a collection of objects using different criteria while chaining them together in a decoupled, logical manner.

Instead of hardcoding complex conditional checks and filtering operations directly into your business entities or UI logic, the Criteria pattern encapsulates each filtering rule as an independent, reusable object.

Essential Architectural Takeaways

Keep these key architectural points in mind when working with or evaluating the Filter / Criteria pattern:

  • Criteria Interface: Declares a contract—typically a method like meetCriteria(List<Item> items)—that returns a filtered sublist of objects satisfying the condition.
  • Atomic Filtering: Individual concrete criteria classes focus strictly on a single attribute or condition (e.g., filtering persons by gender, marital status, or age).
  • Logical Composition: Complex business rules are created by combining multiple criteria objects using composite criteria classes such as AndCriteria, OrCriteria, or NotCriteria.
  • Zero Coupling: The domain objects being filtered have zero dependency on or knowledge of the criteria checking them, keeping your model clean and lightweight.

Key Architectural Benefits

Implementing the Criteria pattern brings strong software engineering advantages:

  • Open/Closed Principle: You can add brand-new filtering conditions or combine existing ones without modifying existing criteria classes or the objects being filtered.
  • High Reusability & Testability: Each criterion can be unit-tested in isolation and reused across completely different parts of the application.
  • Clean Readability: Eliminates deeply nested if-else structures in favor of readable, chained expressions.

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=qpkeBCOk7JA

Click the below Image to Enlarge

Tuesday, 1 October 2013

Filter or Criteria Design Pattern – Implementation

Master Practical Java Architecture & Design Patterns!

Subscribe to Ram N Java for clean coding tutorials, GoF design patterns, and real-world system implementations!

🔔 Subscribe to Ram N Java

The Challenge of Dynamic Collection Filtering

In real-world applications, systems frequently need to filter collections of business entities—such as filtering employees, products, or users based on dynamic conditions like gender, marital status, department, or price ranges.

Writing monolithic helper methods packed with tangled if-else blocks or hardcoded query conditions creates rigid, fragile code that is difficult to maintain and expand. The Filter or Criteria Design Pattern solves this problem by encapsulating filtering rules as first-class objects.

Hands-On Java Implementation Architecture

Implementing the Criteria pattern in Java follows a modular, object-oriented blueprint:

  • Model Class: A standard POJO (e.g., Person) containing attributes such as name, gender, and marital status.
  • Criteria Interface: Declares the filtering contract: public List<Person> meetCriteria(List<Person> persons);
  • Concrete Criteria: Classes implementing the interface to enforce atomic rules, such as CriteriaMale, CriteriaFemale, and CriteriaSingle.
  • Logical Combinators: Classes like AndCriteria and OrCriteria that combine multiple criteria objects to evaluate complex conditions without modifying individual filters.

Key Architectural Benefits

Structuring your business logic using the Criteria pattern delivers immediate software design benefits:

  • Open/Closed Principle: Add new filtering criteria or new logical operators without altering existing criteria classes or the domain entity.
  • High Testability & Reusability: Every filtering rule is isolated in its own class, making unit testing straightforward and enabling reuse across different layers.
  • Composability: Easily assemble complex boolean logic at runtime by chaining criteria objects dynamically.

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=3-KmA2dIHT4

Click the below Image to Enlarge
Filter or Criteria Design Pattern – Implementation - Class Diagram


























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;
}
}


Criteria.java

import java.util.List;

public interface Criteria
{
public List<Person> meetCriteria(List<Person> persons);
}


MaleCriteria.java

import java.util.ArrayList;
import java.util.List;

public class MaleCriteria implements Criteria
{
// Return the List of Persons who are male
@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;
}
}


FemaleCriteria.java

import java.util.ArrayList;
import java.util.List;

public class FemaleCriteria implements Criteria
{
// Return the List of Persons who are female
@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;
}
}


MarriedCriteria.java

import java.util.ArrayList;
import java.util.List;

public class MarriedCriteria implements Criteria
{
// Return the List of Persons who are Married
@Override
public List<Person> meetCriteria( List<Person> persons )
{
List<Person> marriedPersons = new ArrayList<Person>();
for( Person person : persons )
{
if( person.getMaritalStatus().equalsIgnoreCase("Married") )
{
marriedPersons.add(person);
}
}
return marriedPersons;
}
}


NotMarriedCriteria.java

import java.util.ArrayList;
import java.util.List;

public class NotMarriedCriteria implements Criteria
{

// Return the List of Persons who are not Married
@Override
public List<Person> meetCriteria( List<Person> persons )
{
List<Person> notMarriedPersons = new ArrayList<Person>();
for( Person person : persons )
{
if( person.getMaritalStatus().equalsIgnoreCase("notMarried") )
{
notMarriedPersons.add(person);
}
}
return notMarriedPersons;
}
}


CriteriaOrCondition.java


import java.util.List;

public class CriteriaOrCondition implements Criteria 
{
private Criteria criteria; /* male or female or married or notMarried Criteria  */
private Criteria otherCriteria; /* male or female or married or notMarried Criteria  */

public CriteriaOrCondition( Criteria criteria, Criteria otherCriteria )
{
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

// This will perform OR operation of two Criteria results
@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;
}
}


CriteriaAndCondition.java

import java.util.List;

public class CriteriaAndCondition implements Criteria
{

private Criteria criteria;   /* male or female or married or notMarried Criteria  */
private Criteria otherCriteria; /* male or female or married or notMarried Criteria  */

public CriteriaAndCondition( Criteria criteria, Criteria otherCriteria )
{
this.criteria = criteria;
this.otherCriteria = otherCriteria;
}

// This will perform AND operation of two Criteria results
@Override
public List<Person> meetCriteria( List<Person> persons )
{
List<Person> firstCriteriaPersons = criteria.meetCriteria(persons);
return otherCriteria.meetCriteria(firstCriteriaPersons);
}
}


CriteriaPatternDemo.java

public class CriteriaPatternDemo
{
public static void main(String[] args)
{
List<Person> persons = new ArrayList<Person>();

persons.add(new Person("Robert", "Male", "NotMarried"));
persons.add(new Person("John", "Male", "Married"));
persons.add(new Person("Mike", "Male", "NotMarried"));
persons.add(new Person("Bobby", "Male", "NotMarried"));
persons.add(new Person("Laura", "Female", "Married"));
persons.add(new Person("Diana", "Female", "NotMarried"));

printPersons(persons);

System.out.println("---------------------------------------------------------------------");

Criteria male = new MaleCriteria();

System.out.println("Males: ");
printPersons(male.meetCriteria(persons));

Criteria female = new FemaleCriteria();

System.out.println("\nFemales: ");
printPersons(female.meetCriteria(persons));

Criteria notMarried = new NotMarriedCriteria();

System.out.println("\nNotMarried: ");
printPersons(notMarried.meetCriteria(persons));

Criteria married = new MarriedCriteria();

System.out.println("\nMarried: ");
printPersons(married.meetCriteria(persons));

Criteria marriedMale = new CriteriaAndCondition(married, male);

System.out.println("\nMarried and Male: ");
printPersons(marriedMale.meetCriteria(persons));

Criteria notMarriedOrFemale = new CriteriaOrCondition(notMarried, female);

System.out.println("\nNotMarried Or Female");
printPersons(notMarriedOrFemale.meetCriteria(persons));
}

public static void printPersons(List<Person> persons)
{
for (Person person : persons)
{
System.out.println("Person : [ Name : " + person.getName() + ", Gender : " + person.getGender() + ", Marital Status : " + person.getMaritalStatus() + " ]");
}
}
}

Output

Person : [ Name : Robert, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Bobby, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]
Person : [ Name : Diana, Gender : Female, Marital Status : NotMarried ]
---------------------------------------------------------------------
Males: 
Person : [ Name : Robert, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Mike, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Bobby, Gender : Male, Marital Status : NotMarried ]

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

NotMarried: 
Person : [ Name : Robert, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Mike, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Bobby, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Diana, Gender : Female, Marital Status : NotMarried ]

Married: 
Person : [ Name : John, Gender : Male, Marital Status : Married ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]

Married and Male: 
Person : [ Name : John, Gender : Male, Marital Status : Married ]

NotMarried Or Female
Person : [ Name : Robert, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Mike, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Bobby, Gender : Male, Marital Status : NotMarried ]
Person : [ Name : Diana, Gender : Female, Marital Status : NotMarried ]
Person : [ Name : Laura, Gender : Female, Marital Status : Married ]

Sunday, 29 September 2013

Filter or Criteria Design Pattern - Introduction

Master Core Java Architecture & Design Patterns!

Subscribe to Ram N Java for clean code principles, GoF design patterns, and step-by-step software engineering tutorials!

🔔 Subscribe to Ram N Java

What is the Filter or Criteria Design Pattern?

The Filter Design Pattern (also frequently referred to as the Criteria Design Pattern) is a structural design pattern that enables developers to filter a set of objects using distinct criteria and chain them together in a decoupled, logical manner.

In software development, applications often need to filter collections based on varied, continuously changing requirements. Embedding conditional business filtering directly into services, controllers, or database queries creates tight coupling and rigid code. The Filter pattern provides an elegant way to separate filtering logic from core business entities.

Core Concepts & Participants

The structural anatomy of the Filter / Criteria pattern revolves around modular, reusable components:

  • Criteria Interface: Declares a contract—typically meetCriteria(List<Item> items)—defining how a collection of objects is evaluated and filtered.
  • Concrete Criteria: Individual classes that implement the criteria interface to apply specific, atomic filtering rules (e.g., filtering users by status, role, or date).
  • Composite Criteria: Structural combinators like AndCriteria and OrCriteria that combine multiple criteria objects using boolean logic to evaluate complex conditions dynamically.
  • Target Model / Entity: The domain objects being filtered, which remain completely decoupled from and unaware of the filtering logic.

Key Architectural Benefits

Adopting the Criteria pattern introduces major structural advantages into your codebase:

  • Open/Closed Principle: You can create new criteria filters or novel logical combinations without modifying existing filters or domain objects.
  • Single Responsibility Principle: Each criteria class encapsulates exactly one filtering condition, making it easy to understand and test.
  • Composable Flexibility: Dynamic chains of filters can be assembled on the fly at runtime based on user inputs or system configurations.

Related Tutorials from Ram N Java


Click here to watch in Youtube : https://www.youtube.com/watch?v=q0SmOyn2Awg

Click the below Image to Enlarge
Filter or Criteria Design Pattern - Introduction

Tutorials