我有一个我真的不喜欢的大型开关盒,但我似乎找不到优雅的替代解决方案。 我们正在构建一个JavaEE平台,用户可以在其中创建项目。列出的方法用于确定向用户显示的状态消息,这取决于许多因素,例如用户类型(我们有2),项目状态,项目的支付状态等等。大多数这些因素必须以编程方式确定,最终会出现这种大型交换机案例:
public List<String> getToDoMessages(Project project) {
UserAccount user = securitySession.getLoggedInAccount();
switch (user.getAccountType()) {
case EXPERT:
return getExpertToDoMessages(project, user);
case COMPANY:
return getCompanyToDoMessages(project, user);
default:
return new ArrayList<>();
}
}
private List<String> getCompanyToDoMessages(Project project, UserAccount user) {
List<String> ret = new ArrayList<>();
switch (project.getProjectState()) {
case OPEN_FOR_APPLICATION:
ret.add("projectToDo_company_applicationDeadlineNotPassed");
break;
case SELECT_APPLICATION:
ret.add("projectToDo_company_selectApplicant");
break;
case IN_PROGRESS:
ret.add("projectToDo_company_inProgress");
break;
case TEAM_PAYMENT_DISTRIBUTION:
ret.add("projectToDo_company_teamPaymentDistribution");
break;
case CONFIRM_INVOICES:
if (projectAssessmentService.hasAssessed(user, project)) {
ret.add("projectToDo_company_confirmInvoices");
} else {
ret.add("projectToDo_company_assessProject");
}
break;
default:
break;
}
return ret;
}
private List<String> getExpertToDoMessages(Project project, UserAccount user) {
ExpertPerson expert = securitySession.getExpert();
List<String> ret = new ArrayList<>();
switch (project.getProjectState()) {
case OPEN_FOR_APPLICATION:
if (projectService.hasAlreadyApplied(expert, project)) {
if (projectService.hasAlreadyAppliedAsPerson(expert, project)) {
ret.add("projectToDo_expert_appliedAsSinglePerson");
}
if (projectService.hasAlreadyAppliedAsTeam(expert, project)) {
ret.add("projectToDo_expert_appliedAsTeam");
}
} else {
if (projectService.canApply(expert, project)) {
ret.add("projectToDo_expert_openForApplication");
}
}
break;
case SELECT_APPLICATION:
ret.add("projectToDo_expert_selectApplicant");
break;
case IN_PROGRESS:
ret.add("projectToDo_expert_inProgress");
break;
case TEAM_PAYMENT_DISTRIBUTION:
Application application = project.getSelectedApplication();
if (application.isSingleApplication()) {
throw new IllegalStateException("Illegal state TEAM_PAYMENT_DISTRIBUTION for project that has selected a single application");
}
ExpertTeam team = application.getExpertTeam();
if (team.getLeader().equals(expert)) {
ret.add("projectToDo_expert_teamLeaderPaymentDistribution");
} else {
ret.add("projectToDo_expert_teamMemberPaymentDistribution");
}
break;
case CONFIRM_INVOICES:
if (projectAssessmentService.hasAssessed(user, project)) {
ret.add("projectToDo_expert_confirmInvoices");
} else {
ret.add("projectToDo_expert_assessProject");
}
break;
default:
break;
}
return ret;
}
此版本没有列出所有可能性,例如项目类型的区别仍然缺失。当然,我至少可以将语句中的代码移动到单独的方法中,但我确信必须有一个更优雅的解决方案。有谁知道这里可能适用的好模式?
提前致谢!
答案 0 :(得分:4)
重构switch
语句有三条好路径。
Map
。这允许您预先构建工具,甚至可以允许您从外部配置文件配置工具。这里的缺点是你必须跳过一些箍来增加逻辑。enum
。这可能比Map
更灵活,因为您可以在每个enum
内编码逻辑,但有一些缺点。有些人认为enum
中的编码逻辑是一件坏事(我没有)。此外,enum
s只能static
这一事实可能会让您的工作变得不那么容易。Project
对象具有getToDoMessages
方法等。这可能会导致一些非常复杂的管理问题,因为所有getToDoMessages
方法都分布在整个代码中,而不是分布在一个模块中他们现在 - 但请将此选项视为一个好选项,因为它通常是最灵活的选项。 Map
路线示例:
Map<Integer,String> companyToDos = new HashMap<>();
static {
companyToDos.put(OPEN_FOR_APPLICATION, "projectToDo_company_applicationDeadlineNotPassed");
companyToDos.put(SELECT_APPLICATION, "projectToDo_company_selectApplicant");
companyToDos.put(IN_PROGRESS, "projectToDo_company_inProgress");
companyToDos.put(TEAM_PAYMENT_DISTRIBUTION, "projectToDo_company_teamPaymentDistribution");
companyToDos.put(CONFIRM_INVOICES_ASSESSED, "projectToDo_company_confirmInvoices");
companyToDos.put(CONFIRM_INVOICES_UNASSESSED, "projectToDo_company_assessProject");
}
采用enum
路线的示例:
enum AccountType {
EXPERT{
@Override
List<String> getToDoMessages(Project project) {
return project.getState().getExpertToDoMessages();
}
},
COMPANY{
@Override
List<String> getToDoMessages(Project project) {
return project.getState().getCompanyToDoMessages();
}
};
abstract List<String> getToDoMessages(Project project);
}
enum ProjectState {
OPEN_FOR_APPLICATION{
@Override
List<String> getExpertToDoMessages(Project project) {
return ...
}
@Override
List<String> getCompanyToDoMessages(Project project) {
return ...
}
},
SELECT_APPLICATION{
@Override
List<String> getExpertToDoMessages(Project project) {
return ...
}
@Override
List<String> getCompanyToDoMessages(Project project) {
return ...
}
};
abstract List<String> getExpertToDoMessages(Project project);
abstract List<String> getCompanyToDoMessages(Project project);
}