How would you describe the Filter pattern in C ? (Question For - Junior Level Developer)
Question
How would you describe the Filter pattern in C ? (Question For – Junior Level Developer)
Brief Answer
Brief Answer: Filter Pattern in C#
The Filter (or Criteria) pattern is a behavioral design pattern that lets you define a set of criteria and apply them to a collection of objects to select a matching subset. Its primary strength lies in decoupling the object selection logic from the objects themselves.
How it Works:
- Criteria Interface (e.g.,
ICriteria<T>): Defines a common method (likeMeetCriteria) that all filters must implement. This enables polymorphism, treating different filters uniformly. - Concrete Criteria Classes: Implement the interface, encapsulating specific filtering rules (e.g.,
CategoryCriteriafor products). - Filter Application: A mechanism iterates through the collection, applying the chosen filter(s).
Key Benefits (Good to Convey):
- Decoupling & Flexibility: Separates “what to filter” from “how to filter,” allowing you to add new criteria without modifying core object classes.
- Extensibility & Maintainability: New filters are easily added by creating new concrete criteria classes, adhering to the Open/Closed Principle (open for extension, closed for modification). This makes code easier to test and maintain.
- Real-World Example: Filtering a list of products in an e-commerce application by category, price, or brand. Different filters can be combined or used independently without complex
if-elsechains.
In C#, this often involves using interfaces and generics (ICriteria<T>) with List<T> collections.
Super Brief Answer
Super Brief Answer: Filter Pattern in C#
The Filter pattern is a behavioral pattern used to select a subset of objects from a collection based on defined criteria. It decouples the filtering logic from the objects.
It achieves this by using a common ICriteria interface for specific filter implementations. This promotes flexibility and extensibility, allowing new filters to be added easily (Open/Closed Principle).
A common example is filtering products in an e-commerce system by category or price.
Detailed Answer
The Filter design pattern (also known as the Criteria pattern) is a behavioral design pattern that allows you to define a set of criteria (filters) and apply them to a collection of objects to select a subset that matches those criteria. Its core strength lies in promoting loose coupling by separating the object selection logic from the objects themselves, making your code more flexible and maintainable.
Key Concepts & Related Terms
Behavioral Patterns, Data Filtering, Criteria-Based Selection, Object Decoupling, Polymorphism, Open/Closed Principle.
Core Principles of the Filter Pattern
The Filter pattern achieves its goals through a few key components and principles:
-
Criteria Interface
This interface declares a common method that each concrete filter must implement (e.g.,
MeetCriteria). This ensures all filters have a consistent way of checking if an object meets their specific criteria. The interface acts as a contract, enabling polymorphism, which means you can treat different filter types uniformly, simplifying the code that applies the filters. -
Concrete Criteria Classes
These classes implement the criteria interface and contain the actual filtering logic. For instance, a
CategoryCriteriaclass would implement the interface, and itsMeetCriteriamethod would check if a product’s category matches the desired value. Each concrete criteria class encapsulates a specific filtering rule. -
Filter Application Mechanism
This part of the pattern handles the process of iterating through the collection of objects and applying the chosen filter(s). It decouples the filtering process from the objects being filtered and the filter criteria themselves. This could be as simple as a loop that calls the filter’s method for each object in the collection.
-
Enhanced Flexibility and Extensibility
Because of the decoupling provided by the interface, you can introduce new filters simply by creating a new class that implements the criteria interface. No changes are needed to the core objects, the collection, or the filtering application logic. This makes the codebase more maintainable and adaptable to changing requirements. It’s easier to test individual filters, and adding new filtering options doesn’t risk breaking existing functionality. It’s a practical example of the Open/Closed Principle — open for extension, closed for modification.
Interview Preparation Tips
When discussing the Filter pattern in an interview, consider these points:
-
1. Emphasize Decoupling
Highlight that decoupling is a key advantage. Explain how the Filter pattern allows you to add new filtering criteria without modifying the core object classes or the collection processing logic. Use a relatable example, like filtering
Productobjects in an e-commerce system by various criteria. Each criterion is encapsulated in its own class, keeping theProductclass clean. -
2. Provide a Real-World Example
An example like filtering products in an e-commerce application (by price range, brand, category, etc.) is highly effective. Mention how different filters can be combined (e.g., “Electronics AND Price < $500”) or used independently. Explain how this flexibility is achieved without creating a tangled mess of
if-elsestatements. -
3. Highlight Maintainability and Extensibility
Explain that adding a new filter (e.g., a “Size” filter) is straightforward: simply create a new
SizeCriteriaclass implementing the common interface. No changes are required elsewhere in the system. This significantly improves maintainability and extensibility, making individual filters easier to test and reducing the risk of breaking existing functionality when new features are added. Connect this directly to the Open/Closed Principle.
C# Code Example
Here’s a simplified C# example demonstrating the core components of the Filter pattern:
// Example C# structure for Filter Pattern
// 1. Criteria Interface
public interface ICriteria<T>
{
List<T> MeetCriteria(List<T> items);
}
// 2. Concrete Criteria Classes
public class Product
{
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
public class CategoryCriteria : ICriteria<Product>
{
private string _category;
public CategoryCriteria(string category)
{
_category = category;
}
public List<Product> MeetCriteria(List<Product> items)
{
List<Product> filteredItems = new List<Product>();
foreach (var item in items)
{
if (item.Category.Equals(_category, StringComparison.OrdinalIgnoreCase))
{
filteredItems.Add(item);
}
}
return filteredItems;
}
}
// 3. Filter Application (Example Usage)
public class ProductFilterer
{
public List<Product> Filter(List<Product> products, ICriteria<Product> criteria)
{
return criteria.MeetCriteria(products);
}
// Example of combining criteria (e.g., using And/Or patterns for composite filters)
// For brevity, composite filters like AndCriteria or OrCriteria are not shown here.
}
// How to use the Filter Pattern:
/*
List allProducts = new List
{
new Product { Name = "Laptop", Category = "Electronics", Price = 1200m },
new Product { Name = "Smartphone", Category = "Electronics", Price = 800m },
new Product { Name = "Desk Chair", Category = "Furniture", Price = 150m },
new Product { Name = "Headphones", Category = "Electronics", Price = 100m }
};
ICriteria electronicsCriteria = new CategoryCriteria("Electronics");
ProductFilterer filterer = new ProductFilterer();
List electronics = filterer.Filter(allProducts, electronicsCriteria);
Console.WriteLine("Electronics Products:");
foreach (var product in electronics)
{
Console.WriteLine($"- {product.Name} ({product.Category}, ${product.Price})");
}
*/

