java如何在这个特定示例中消除开关
我有一个控制器方法,它从请求中获取数据,并根据请求中的主题变量决定调用函数。(对于项目需要,我不能对每个主题变量使用单独的控制器方法)
现在我使用了switch,但我认为它打破了开闭原则(因为每次添加新类型的主题时,我都必须为switch添加新的案例),而且设计不好,如何重构代码
Subject subject = ... //(type of enum)
JSONObject data = request.getData("data");
switch(subject) {
case SEND_VERIFY:
send_foo1(data.getString("foo1_1"), data.getString("foo1_2"));
break;
case do_foo2:
foo2(data.getInt("foo2_b"), data.getInt("foo2_cc"));
break;
case do_foo3:
do_foo3_for(data.getString("foo3"));
break;
// some more cases
}
# 1 楼答案
虽然我不确定这段代码违反了哪个OO原则,但确实有一种更为激进的方法来实现逻辑:将每个枚举值的处理绑定到枚举类
您需要将处理概括为一个接口:
并为每个枚举值创建具体实现:
一旦有了类层次结构树,就可以将每个枚举值与具体的处理器相关联
这样就不需要在控制器中使用switch语句:
编辑:
根据好的注释,您可以使用
java.util.function.Consumer
函数接口,而不是自定义的SubjectProcessor
接口。您可以决定是编写具体的类还是使用lambda expr构造或者
# 2 楼答案
其他人的答案似乎很好,作为补充,我建议使用
EnumMap
将枚举存储为键,因为它可能比标准Map
更有效。我认为还值得一提的是,策略模式在这里用于实现从Map
调用每个键的特定操作,而无需构建长切换语句# 3 楼答案
您可以在单独的类中维护
Map<Subject, Consumer<JSONObject>> tasks
配置,而不是与if (tasks.containsKey(subject))
代码混合使用。当您需要其他功能时,可以在此地图中配置一个条目