假设我们有“促销作为汇总根”和“规则”来满足促销作为“汇总”。 规则是不同规则元素的集合,这些元素扩展了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方法吗?其他选择?谢谢朋友!
答案 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); }
});
}