【发布时间】:2017-10-12 03:14:46
【问题描述】:
在我的 DDD 项目中,我正在尝试使用 java 枚举来实现状态模式。
在验证行为取决于状态的实体方法时遇到问题。
为了验证,我使用通知模式。
我遵循“始终有效的实体”方法,因此在每个操作中我首先调用“isValidForOperation”验证方法。
这里是代码,只是为了简单起见:
实体:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply the state pattern here
public void start () {
State next = this.state.start ( this );
this.setState ( next );
}
...
}
对状态建模的java枚举:
public enum State {
ASSIGNED {
public State start ( Task task ) {
// Validation method to ensure the operation can be done
assertTaskIsValidForStart ( task );
// Business logic
...
// Return the next state
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" operation
// It will be executed when the current state is not "ASSIGNED"
// So an error would be generated
public State start ( Task task ) {
// I can't apply notification pattern here !!!
// I would have to throw an exception
}
}
验证方法遵循通知模式。 它收集通知对象中所有可能的错误。 此通知对象被传递给异常。 异常被抛出,然后应用层捕获它并将所有错误消息返回给客户端。
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
if ( errorCondition (task) ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
当错误条件与状态之间的无效转换有关时,如何应用通知模式(与状态模式结合)?
有什么想法吗?
更新:
我找到了解决方案。我将依赖于状态的整个操作放在实体中,并将状态模式更细粒度地应用到所需的代码中。这样我就可以应用模式来计算下一个状态,这样我就可以检查是否允许转换并应用通知模式。
代码:
public class Task extends AggregateRoot<TaskId> {
...
private State state;
...
// Operation with behaviour depending on the state
// It's a transition from "ASSIGNED" state to "IN_PROGRESS" state
// I apply fine-grained state pattern here
public void start () {
// Validation method to ensure the operation can be done
// One of the validations will be if the transition is allowed
assertTaskIsValidForStart ( this );
// Business logic
// If it depends on the state, I would apply state pattern delegating to another method
...
// Set the next state
State next = this.nextStateForStart();
this.setState ( next );
}
...
public State currentState() {
return this.state;
}
...
public State nextStateForStart() {
return this.currentState().nextStateForStart();
}
...
}
public enum State {
ASSIGNED {
public State nextStateForstart() {
return ( State.IN_PROGRESS );
}
}
...
// more enum values for other states
...
// Default implementation of "start" transition
// It will be executed when the current state is not "ASSIGNED"
public State nextStateForstart() {
return null;
}
}
public void assertTaskIsValidForStart ( Task task ) {
Notification notification = new Notification();
// Validate the transition is allowed
if ( task.nextStateForStart() == null ) {
notification.addError(...);
}
...
// more errors
...
if ( notification.hasErrors() ) {
throw new TaskNotValidForStartException ( notification.errors() );
}
}
【问题讨论】:
标签: validation design-patterns notifications domain-driven-design state-pattern