规格(Specification)即类/对象的属性,比如产品的颜色、尺寸和价格,如果业务规则的变化和组合很多,而且和规格相关,包括很多的条件判断,那么适合将这些业务规则放到专门的规格对象中,这就是规格模式(Specification Pattern)。
规格模式有三种形式:
- 用于验证,验证一个对象的状态是否符合要求。
- 用于筛选过滤,从一个集合中筛选出符合指定要求的对象。(Java 8可以使用stream 很方便filter出符合条件的对象,不需要用规格模式)
- 按需创建指定规格的产品。
案例:根据颜色、尺寸、价格等规格筛选出指定规格的产品。
下面的代码展示Builder, Factory, Intercepter, Composite 和 Specification模式。
//Builder设计模式
public class Product {
private String name;
private float price;
private Color color;
private ProductSize productSize;
private Product(String name) {
this.name = name;
}
public static Product withName(String name) {
return new Product(name);
}
public Product withColor(Color color) {
this.color = color;
return this;
}
public Product withSize(ProductSize productSize) {
this.productSize = productSize;
return this;
}
public Product withPrice(float price) {
this.price = price;
return this;
}
public String getName() {
return name;
}
public float getPrice() {
return price;
}
public Color getColor() {
return color;
}
public ProductSize getProductSize() {
return productSize;
}
@Override
public String toString() {
return "Product{" +
"name='" + name + '\'' +
", price=" + price +
", color=" + color +
", productSize=" + productSize +
'}';
}
}
enum ProductSize {
SMALL, MEDIUM, LARGE, NOT_APPLICATION
}
//Specifiction模式和Composite模式中定义的抽象接口
public interface ISpecification<T> {
boolean isSatisfiedBy(T candidate);
ISpecification and(ISpecification other); //Factory
ISpecification andNot(ISpecification other); //Factory
ISpecification or(ISpecification other); //Factoy
ISpecification orNot(ISpecification other); //Factory
ISpecification not(); //Factory
}
public abstract class CompositeSpecification<T> implements ISpecification<T> {
@Override
public abstract boolean isSatisfiedBy(T candidate);
@Override
public ISpecification and(ISpecification other) {
return new AndSpecification(this, other);
}
@Override
public ISpecification andNot(ISpecification other) {
return new AndNotSpecification(this, other);
}
@Override
public ISpecification or(ISpecification other) {
return new OrSpecification(this, other);
}
@Override
public ISpecification orNot(ISpecification other) {
return new OrNotSpecification(this, other);
}
@Override
public ISpecification not() {
return new NotSpecification(this);
}
}
//颜色规格类,也是intercepter模式的终结表达式类
public class ColorSpecification extends CompositeSpecification<Product> {
private Color color;
public ColorSpecification(Color color) {
if(color == null) throw new IllegalArgumentException("color is a must");
this.color = color;
}
@Override
public boolean isSatisfiedBy(Product candidate) {
return this.color.equals(candidate.getColor());
}
}
//价格规格类,也是intercepter模式的终结表达式类
public class PriceSpecification extends CompositeSpecification<Product> {
private float price;
public PriceSpecification(float price) {
if(price <= 0) throw new IllegalArgumentException("price must be greater than 0");
this.price = price;
}
public boolean isSatisfiedBy(Product candidate) {
return this.price == candidate.getPrice();
}
}
//低于指定价格规格类,也是intercepter模式的终结表达式类
public class BelowPriceSpecification extends CompositeSpecification<Product> {
private float priceThreshold;
public BelowPriceSpecification(float priceThreshold) {
if(priceThreshold <= 0) throw new IllegalArgumentException("price threshold must be greater than 0");
this.priceThreshold = priceThreshold;
}
public boolean isSatisfiedBy(Product candidate) {
return this.priceThreshold > candidate.getPrice();
}
}
//尺寸规格类,也是intercepter模式的终结表达式类
public class SizeSpecification extends CompositeSpecification<Product> {
private ProductSize size;
public SizeSpecification(ProductSize size) {
if(size == null) throw new IllegalArgumentException("size is a must");
this.size = size;
}
@Override
public boolean isSatisfiedBy(Product candidate) {
return this.size == candidate.getProductSize();
}
}
//规格类和intercepter模式的“and”非终结表达式类
public class AndSpecification<T> extends CompositeSpecification<T> {
private final ISpecification<T> left;
private final ISpecification<T> right;
public AndSpecification(ISpecification<T> left, ISpecification<T> right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate);
}
}
//规格类和intercepter模式的“not and”非终结表达式类
public class AndNotSpecification<T> extends CompositeSpecification<T> {
private final ISpecification<T> left;
private final ISpecification<T> right;
public AndNotSpecification(ISpecification<T> left, ISpecification<T> right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return left.isSatisfiedBy(candidate) && !right.isSatisfiedBy(candidate);
}
}
//规格类和intercepter模式的“or”非终结表达式类
public class OrSpecification<T> extends CompositeSpecification<T> {
private final ISpecification<T> left;
private final ISpecification<T> right;
public OrSpecification(ISpecification<T> left, ISpecification<T> right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return left.isSatisfiedBy(candidate) || right.isSatisfiedBy(candidate);
}
}
//规格类和intercepter模式的“not or”非终结表达式类
public class OrNotSpecification<T> extends CompositeSpecification<T> {
private final ISpecification<T> left;
private final ISpecification<T> right;
public OrNotSpecification(ISpecification<T> left, ISpecification<T> right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return left.isSatisfiedBy(candidate) || !right.isSatisfiedBy(candidate);
}
}
//规格类和intercepter模式的“not”非终结表达式类
public class NotSpecification<T> extends CompositeSpecification<T> {
private final ISpecification<T> spec;
public NotSpecification(ISpecification<T> spec) {
this.spec = spec;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return !spec.isSatisfiedBy(candidate);
}
}
//测试类
public class ProductFindingService {
private List<Product> inMemoryProducts = new ArrayList<>();
{
inMemoryProducts.add(Product.withName("A")
.withColor(Color.RED).withSize(ProductSize.MEDIUM).withPrice(10.00f));
inMemoryProducts.add(Product.withName("B")
.withColor(Color.YELLOW).withSize(ProductSize.SMALL).withPrice(20.00f));
inMemoryProducts.add(Product.withName("C")
.withColor(Color.PINK).withSize(ProductSize.LARGE).withPrice(9.99f));
inMemoryProducts.add(Product.withName("D")
.withColor(Color.WHITE).withSize(ProductSize.SMALL).withPrice(10.00f));
inMemoryProducts.add(Product.withName("E")
.withColor(Color.RED).withSize(ProductSize.NOT_APPLICATION).withPrice(200.00f));
}
/**
* Using lambert expression to select products
*
* @param predicate
* @return
*/
public List<Product> selectBy(Predicate<Product> predicate) {
return inMemoryProducts.stream().filter(predicate).collect(Collectors.toList());
}
/**
* Using specification pattern to select products
*
* @param specification
* @return
*/
public List<Product> selectBy(ISpecification<Product> specification) {
return inMemoryProducts.stream().filter(specification::isSatisfiedBy).collect(Collectors.toList());
}
public static void main(String[] args) {
ProductFindingService productFindingService = new ProductFindingService();
//method 1: using lambda expression to select the products with Color=Red and Price < 20.00
productFindingService.selectBy(e -> e.getColor().equals(Color.RED) && e.getPrice() < 20.00f)
.forEach(System.out::println);
//method 2 using specification pattern to select the products with Color=Red and Price < 20.00
productFindingService.selectBy(new ColorSpecification(Color.RED).and(new BelowPriceSpecification(20.00f)))
.forEach(System.out::println);
}
}
返回 设计模式