规格模式(Specification)

规格(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);
    }
}

返回 设计模式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值