我有一个使用 CDI 的项目。具有状态列表的容器托管服务类。
@ApplicationScoped
public class StateService {
@Inject
MailService mailService;
//Inject some other stuff
private Map<String, State> state = new HashMap<String, State>();
public void makeStateTransition(StateChange stateChange) {
State currentState = state.get(stateChange.getKey());
switch (currentState.stateType) {
case STATE1:
handleState1Transition(stateChange);
case STATE2:
handleState2Transition(stateChange);
case STATE3:
handleState3Transition(stateChange);
}
}
private void handleState1Transition(StateChange stateChange) {
//Do some stuff to handle state and use injected mailsender to send some email
mailService.sendEmail("Send some email");
//if some criteria is right create a new state and set it in the map
State newState = new State();
//Set some variable
state.put(stateChange.getKey(), newState);
}
private void handleState2Transition(StateChange stateChange) {
//Do stuff similar to above, maybe use other injected fields
}
private void handleState3Transition(StateChange stateChange) {
//Do stuff similar to above
}
}
public class State {
public enum StateType {
STATE1, STATE2, STATE3
}
public StateType stateType;
//Bunch of other properties
}
事实证明这是非常程序化的。我对其进行了重构以尝试使其更加面向对象。
@ApplicationScoped
public class StateService {
@Inject
MailService mailSerice;
//Inject some other stuff
private Map<String, State> state = new HashMap<String, State>();
public void makeStateTransition(StateChange stateChange) {
State currentState = state.get(stateChange.getKey());
State newState = currentState.handleStateChange(stateChange, mailService);
state.put(stateChange.getKey(), newState);
}
}
现在 StateService 不需要知道所有的状态转换
public abstract class State {
//Some protected fields shared by all states
public abstract State handleStateChange(StateChange stateChange, MailService mailService);
}
public class SomeState extends State {
//Some properties specific to this state
public State handleStateChange(StateChange stateChange, MailService mailSerice) {
//Do some stuff to handle state and use injected mailsender to send some email
mailSerice.sendEmail("Send some email");
return new SomeOtherState();
}
}
这会产生更好的代码,尤其是随着可能状态数量的增加。问题是让注入的邮件发件人进入需要它的正确状态。有些州可能不需要它,而另一些州可能需要别的东西。因为状态不是由容器创建的,所以它们自己不能使用注入。在状态的构造函数中传递注入的字段是可能的,但是注入的对象可能会在非托管状态中变得“陈旧”?
我求助于在方法调用中将其作为参数发送,这样它应该始终是“新鲜的”。如果需要将许多注入作为参数发送并且在某种程度上感觉错误,则非常麻烦。
您将如何建议如何处理此示例中状态对象所需的注入资源?
请忽略课堂上的任何线程问题。