Specification Pattern
In computer programming, the specification pattern is a particular software design pattern, whereby business rules can be recombined by chaining the business rules together using boolean logic. The pattern is frequently used in the context of domain-driven design.
using System;
using System.Collections.Generic;
namespace opencloseprinciple
{
public enum Color { Red, Green, Blue }
public enum Size { Small, Medium, Large }
public class Product
{
public string Name { get; set; }
public Color Color { get; set; }
public Size Size { get; set; }
public Product(string name, Color color, Size size)
{
this.Name = name;
this.Color = color;
this.Size = size;
}
}
// Specification Pattern
public interface ISpecification<T>
{
bool IsSatisfiedBy(T t);
}
public interface IFilter<T>
{
IEnumerable<T> Filter(IEnumerable<T> items, ISpecification<T> specification);
}
public class ColorSpecification : ISpecification<Product>
{
private readonly Color color;
public ColorSpecification(Color color)
{
this.color = color;
}
public bool IsSatisfiedBy(Product product)
{
return product.Color == this.color;
}
}
public class SizeSpecification : ISpecification<Product>
{
private readonly Size size;
public SizeSpecification(Size size)
{
this.size = size;
}
public bool IsSatisfiedBy(Product product)
{
return product.Size == this.size;
}
}
public class AndSpecification<T> : ISpecification<T>
{
private ISpecification<T> first, second;
public AndSpecification(ISpecification<T> first, ISpecification<T> second)
{
if(first == null || second == null)
throw new ArgumentNullException();
this.first = first;
this.second = second;
}
public bool IsSatisfiedBy(T t)
{
return first.IsSatisfiedBy(t) && second.IsSatisfiedBy(t);
}
}
public class ProductFilter : IFilter<Product>
{
public IEnumerable<Product> Filter(IEnumerable<Product> products,
ISpecification<Product> specification)
{
foreach (var product in products)
if(specification.IsSatisfiedBy(product))
yield return product;
}
}
class Program
{
static void Main(string[] args)
{
var apple = new Product("apple", Color.Green, Size.Small);
var tree = new Product("tree", Color.Green, Size.Large);
var house = new Product("house", Color.Blue, Size.Large);
var products = new Product[] { apple, tree, house };
var productFilter = new ProductFilter();
foreach (var product in productFilter.Filter(
products,
new ColorSpecification(Color.Green)))
{
Console.WriteLine($" - {product.Name} is green");
}
foreach (var product in productFilter.Filter(
products,
new AndSpecification<Product>(
new ColorSpecification(Color.Green),
new SizeSpecification(Size.Large)
)))
{
Console.WriteLine($" - {product.Name} is green and large");
}
}
}
}
Comments
Post a Comment