The class ProductService, below, gets products based on different filters like by date, country, etc., from a database. ProductsService doesn't follow OCP, as adding new filter like getting products by Price requires changing the ProductsService code. How it can be fixed? Any suggestions/comments would be really helpful.
public class ProductsService : IProductsService
{
public FilteredProducts GetProductsByDate(DateTime startDate, DateTime EndDate)
{
//.....
}
public FilteredProducts GetProductsByCountry(string country)
{
//.....
}
public FilteredProducts GetProductsByCity(string city)
{
//.....
}
}
public class FilteredProducts
{
public IEnumerable<Product> Products{set;get;}
public int uniqueProducts { set; get; }
}
public class Product
{
public int ID{set;get;}
public string Name{set;get;}
public decimal Cost{set;get;}
}
Best way is to represent each operation as separate class.
public interface IProductFilter
{
FilteredProducts GetProducts();
}
public class GetProductsByDate : IProductFilter
{
private DateTime _startDate;
private DateTime _endDate;
public GetProductsByDate(DateTime startDate, DateTime EndDate)
{
_startDate = startDate;
_endDate = EndDate;
}
public FilteredProducts GetProducts()
{
// filter
}
}
You can then pass this implementation into your service, where it gets executed.
public class ProductsService : IProductsService
{
public FilteredProducts FilterProducts(IProductFilter filter)
{
// execute the filter
// return the products
}
}
You could even go as far as turning it into generic Command (for example here) and executing all your database logic through it, ditching the "service" anti-pattern.