我正在阅读Eric Evans撰写的精彩书籍“领域驱动设计”。在他的书中,Eric描述了两个不同的概念:规范模式和策略。
以下是规范的示例:
public interface ProjectSpecification {
public boolean isSatisfiedBy(Project p);
}
public class ProjectIsOverdueSpecification implements ProjectSpecification {
public boolean isSatisfiedBy(Project p) { … }
}
//client:
if {
(projectIsOverdueSpecification.isSatisfiedBy(theCurrentProject) { … }
}
以下是政策的示例:
public class CargoBooking {
private OverBookingPolicy overBookingPolicy = new OverBookingPolicy();
public int makeBooking(Cargo cargo, Voyage voyage) {
if (!overbookingPolicy.isAllowed(cargo, voyage))
return –1;
int confirmation = orderConfirmationSequence.next();
voyage.addCargo(cargo, confirmation);
return confirmation;
}
}
public OverBookingPolicy {
public boolean isAllowed(Cargo cargo, Voyage voyage) {
return (cargo.size() + voyage.bookedCargoSize()) <= (voyage.capacity() * 1.1);
}
}
我知道政策实际上是一种策略,但在上面的两个例子中,绝对没有区别。所以我现在的问题是:这两种模式有什么区别?这两种模式都明确了业务规则,为什么我们要区分这两种模式呢?对我来说,两者都是谓词。
答案 0 :(得分:41)
SPECIFICATION背后的主要思想是它是一个谓词,通常意味着使用逻辑运算符
例如,我们可以说盒子是红色的,即满足一些RedSpecification。我们可以声明一些GreenSpecification,甚至是复合RedOrGreenSpecification。 如果我们有一些支持规范逻辑操作的高级框架,它可以是规范是对既定形式主义的改编(Eric Evans DDD,第274页)
BoxSpecification redBoxSpec = BoxSpecification.forColor(BoxColor.RED);
BoxSpecification greenBoxSpec = BoxSpecification.forColor(BoxColor.GREEN);
BoxSpecification redOrGreenBoxSpec = redBoxSpec.or(greenBoxSpec);
然后我们可以使用规范来查询某些存储库中的所有红色/绿色框:
Collection<Box> boxes = boxRepository.findAll(redOrGreenBoxSpec);
至于POLICY - 它是STRATEGY模式的变体,但其主要目的是封装业务规则是一种声明形式。
技术上 - 它并不总是战略的直接实现 - 在第一阶段它可以只是一个单独的类(如蓝皮书的第一章所示),但它可以在以后轻松扩展
政策是被称为战略的设计模式的另一个名称。据我们所知,这通常是需要替换不同规则的动机,这里不需要这些规则。但是我们试图捕获的概念确实符合策略的含义,这是域驱动设计中同样重要的动机
例如,我们在1月份用黄色方框包装礼物,在2月份用红色方框包装
public class Box{
public BoxColor getColor(){}
public void recolor(BoxColor color){}
}
public class BoxFactory{
public Box createDefaultBox(SomeDate date){
NewBoxPolicy boxPolicy = PolicyRegistry.getNewBoxPolicyForDate(date);
Box box = new Box();
boxPolicy.prepareBox(box);
return box;
}
}
public interface NewBoxPolicy{
void prepareBox(Box box);
}
public class FebruaryNewBoxPolicy implements NewBoxPolicy{
public void prepareBox(Box box) { box.recolor(BoxColor.RED}; }
}
public class JanuaryNewBoxPolicy implements NewBoxPolicy{
public void prepareBox(Box box) { box.recolor(BoxColor.YELLOW}; }
}
public class PolicyRegistry{
public static NewBoxPolicy getNewBoxPolicyForDate(SomeDate date){
switch (date.month()){
case SomeMonth.JANUARY: return JANUARY_NEW_BOX_POLICY;
case SomeMonth.FEBRUARY: return FEBRUARY_NEW_BOX_POLICY;
default: throw new AssertionError();
}
}
了解POLICY可以封装操作非常重要,而SPECIFICATION只描述对象的属性(这些属性既可以满足也可以不满足业务要求)。当然,一些验证POLICY可以使用SPECIFICATION来检查是否满足要求。
因此,您可以在项目中拥有许多不同的SPECIFICATION实例,并且他们可以从业务角度描述有效和无效对象。实际上,规范完全没有意义:例如,如果您有产品搜索站点,用户可以指定搜索名为“XBOX”的产品的请求,但是使用供应商名称“Sony”,如果知道只有特定供应商可以生产未在您的模型中捕获的特定产品。
POLICY的一个重要方面是它的意图是封装实际业务规则(因此代码不会分散到项目的不同部分),因此当规则发生变化时,您可以轻松找到相应的班级。因此,您的项目中可以有许多规范,但可管理的政策数量,以及那些政策应该易于查找和更改。
P.S。请注意,这篇文章只是一个例子而不是过度工程的许可证,当然你应该使用最简单的设计,这是常识问题。