1. 程式人生 > >規格模式(Specification Pattern)。

規格模式(Specification Pattern)。

定義

組合模式+策略模式。

通用原始碼

規格模式非常重要,他巧妙的實現了物件篩選功能。我們來看其通用原始碼,首先看抽象規格書,如下所示。

public interface ISpecification {
	/**
	 * 候選者是否滿足需求
	 * 
	 * @param candidate
	 * @return
	 */
	boolean isSatisfiedBy(Object candidate);

	/**
	 * and操作
	 * 
	 * @param spec
	 * @return
	 */
	ISpecification and(ISpecification spec);

	/**
	 * or操作
	 * 
	 * @param spec
	 * @return
	 */
	ISpecification or(ISpecification spec);

	/**
	 * not操作
	 * 
	 * @return
	 */
	ISpecification not();
}

組合規格書實現與或非的演算法,如下所示。

public abstract class CompositeSpecification implements ISpecification {
	@Override
	public ISpecification and(ISpecification spec) {
		return new AndSpecification(this, spec);
	}

	@Override
	public ISpecification or(ISpecification spec) {
		return new OrSpecification(this, spec);
	}

	@Override
	public ISpecification not() {
		return new NotSpecification(this);
	}
}

與或非規格書程式碼分別如下所示。

public class AndSpecification extends CompositeSpecification {
	// 傳遞兩個規格書進行and操作
	private ISpecification left;
	private ISpecification right;

	public AndSpecification(ISpecification left, ISpecification right) {
		this.left = left;
		this.right = right;
	}

	@Override
	public boolean isSatisfiedBy(Object candidate) {
		return this.left.isSatisfiedBy(candidate) && this.right.isSatisfiedBy(candidate);
	}

}
public class OrSpecification extends CompositeSpecification {
	// 左右兩個規格書
	private ISpecification left;
	private ISpecification right;

	public OrSpecification(ISpecification left, ISpecification right) {
		this.left = left;
		this.right = right;
	}

	@Override
	public boolean isSatisfiedBy(Object candidate) {
		return this.left.isSatisfiedBy(candidate) || this.right.isSatisfiedBy(candidate);
	}

}
public class NotSpecification extends CompositeSpecification {
	// 傳遞一個規格書
	private ISpecification spec;

	public NotSpecification(ISpecification spec) {
		this.spec = spec;
	}

	@Override
	public boolean isSatisfiedBy(Object candidate) {
		return this.isSatisfiedBy(spec);
	}

}

以上一個介面、一個抽象類、3個實現類只要在適用規格模式的地方都完全相同,不用做任何的修改,大家閉著眼chao6就成,要修改的是下面的規格書——業務規格書,如下所示。

public class BizSpecification extends CompositeSpecification {
	// 基準物件
	@SuppressWarnings("unused")
	private Object obj;

	public BizSpecification(Object obj) {
		this.obj = obj;
	}

	@Override
	public boolean isSatisfiedBy(Object candidate) {
		// 根據基準物件和候選物件,進行業務判斷,返回boolean
		return false;
	}

}

然後就是看怎麼使用了,場景類如下所示。

public class Client {
	public static void main(String[] args) {
		// 待分析的物件
		ArrayList<Object> list = new ArrayList<Object>();
		// 定義兩個業務規格書
		ISpecification spec1 = new BizSpecification(new Object());
		ISpecification spec2 = new BizSpecification(new Object());
		// 規則的呼叫
		for (Object obj : list) {
			if (spec1.and(spec2).isSatisfiedBy(obj)) { // and操作
				System.out.println(obj);
			}
		}
	}
}

規格模式已經是一個非常具體的應用框架了(相對於23個設計模式),大家遇到類似多個物件中篩選查詢,或者業務規則不適於放在任何已有實體或值物件中,而且規則的變化和組合會掩蓋那些領域物件的基本含義,或者是想自己編寫一個類似LINQ的語言工具的時候就可以照搬這部分程式碼,只要實現自己的邏輯規格書即可。