DDD聚合根,以哪种方式创建具有不同类型的新子聚合元素?工厂方法?

时间:2018-12-19 10:02:42

标签: java php oop domain-driven-design aggregateroot

假设我们有“促销作为汇总根”和“规则”来满足促销作为“汇总”。 规则是不同规则元素的集合,这些元素扩展了Abstract类Rule。

据我了解,我可以使用工厂方法,例如:

class Promotion (
    PromotionIdentity $identity,
    string $name,
){
    $this->identity = $identity;
    $this->name = $name;
    $this->rules = new RuleCollection();   
}

public function addRule(
    RuleIdentity $ruleIdentity,
    RuleType $ruleType,
    array $configuration
) {
    if (RuleType::EMAIL_LIST === $ruleType->value()) {
        $makeRule = new EmailListRule($ruleIdentity, $configuration);
        $this->rules->add($makeRule);
    }

    if (RuleType::MIN_ARTICLES === $ruleType->value()) {
        $makeRule = new MinimumArticlesRule($ruleIdentity, $configuration);
        $this->rules->add($makeRule);
    }

    ... and so on, for example 15 rules
}

我认为这会增长很多,我在这里看到代码的味道。

可以将规则创建的逻辑保留在聚合根中吗?我们可以将规则创建的责任移至工厂内的应用程序服务,并将生成的规则传递给addRule方法吗?其他选择?谢谢朋友!

1 个答案:

答案 0 :(得分:-1)

  

满足晋升优惠的规则

好吧,AR无法保存其他AR的实例,因此Rule在这里可能不是AR。此外,乍一看,并且不了解您的域,从域的角度来看,Rule甚至成为实体(从存储的角度来看也是如此)的理由很少。 Rule不能只是一个值对象,如果需要更改可以完全替换吗?

//Application service
changePromotionRules(String promotionId, Set<Map<String, String>> rulesConfig) {
    Set<Rule> rules = ruleFactory.rulesFromConfig(rulesConfig);
    Promotion promotion = promotionRepository.promotionOfId(new PromotionIdentity(promotionId));
    promotion.changeRules(rules);
}

//Promotion AR
changeRules(Set<Rule> rules) {
    validateRules(rules);
    this.rules = rules;
}

上面的示例假定类似CRUD的行为,其中所有规则都被一次替换,但是您可以使用更精细的addRule / removeRule操作(可能更适合)来进行相同的操作。

如果您在UI行为(例如一次性保存的所有规则)和域(例如addRule / removeRule)之间有脱节,则可以在应用程序服务层中进行调整。

例如

//Application service
changePromotionRules(String promotionId, Set<Map<String, String>> rulesConfig) {
    Set<Rule> rules = ruleFactory.rulesFromConfig(rulesConfig);
    Promotion promotion = promotionRepository.promotionOfId(new PromotionIdentity(promotionId));
    withSetDiffBetween(rules, promotion.rules(), new SetDiffHandler<Rule>() {
         withAdd(Rule rule) { promotion.addRule(rule); }
         withRemove(Rule rule) { promotion.removeRule(rule); }
    });
}