Java 重构if语句以使用适当的模式
我有一个枚举,其中包含一些状态:Java 重构if语句以使用适当的模式,java,oop,design-patterns,Java,Oop,Design Patterns,我有一个枚举,其中包含一些状态: enum State { A, B, C, D } 以及具有相应状态的对象: class MyObject { State state; } 我需要编写一个算法,它接受两个MyObject实例,并根据这些实例的特定状态执行某些操作: void doWork(MyObject o1, MyObject o2) { if (o1.state == A && o2.state == A)
enum State
{
A,
B,
C,
D
}
以及具有相应状态的对象:
class MyObject
{
State state;
}
我需要编写一个算法,它接受两个MyObject实例,并根据这些实例的特定状态执行某些操作:
void doWork(MyObject o1, MyObject o2)
{
if (o1.state == A && o2.state == A)
{
// do something
}
else if (o1.state == A && o2.state == B)
{}
// etc for all combinations...
}
显然,这种方法有很多问题,我想将其更改为理想情况下摆脱if/else语句
这种要求有什么模式吗
谢谢你能做的,虽然我不确定会有多好,是两个状态
值的所有可能组合的某种矩阵;然后可以使用o1.state
和o2.state
作为该矩阵的索引
您可以在该矩阵中存储不同的内容:
- 一个唯一值,可以用作
块的识别值,该块将替换开关
块——实际上没有多大改进if。。否则。。else
- 命令对象。(查一下地图。)
If
语句,那么第二个选项可能会更好;但是,请注意,您的代码将不再像if
/switch
块那样在一个位置靠得很近,而是分布在多个不同的命令对象/类上
// forgive my syntax errors etc., my Java has definitely gone a little rusty!
interface WorkCommand {
public abstract void run(MyObject o1, MyObject o2);
}
...
Map<Pair<State,State>, WorkCommand> commands;
// ^ pseudo-code type for your command look-up map; type Pair<X,Y> doesn't exist,
// so replace this with something sensible!
void doWork(MyObject o1, MyObject o2)
{
WorkCommand worker = commands.get(new Pair<State,State>(o1, o2));
worker.run(o1, o2);
}
//请原谅我的语法错误等,我的Java肯定有点生锈了!
接口工作命令{
公开摘要无效运行(MyObject o1,MyObject o2);
}
...
地图命令;
//^命令查找映射的伪代码类型;类型对不存在,
//所以,用一些合理的东西来代替它!
空道具(对象o1、对象o2)
{
WorkCommand worker=commands.get(新对(o1,o2));
工人运行(o1,o2);
}
我可能已经这样做了,至少它更具可读性
void doWork(MyObject o1, MyObject o2) {
switch (o1.state) {
case A: {
switch (o2.state) {
case A: {
break;
}
case B: {
break;
}
}
break;
}
}
}
构造此结构的一种方法是,在枚举中可以有一个抽象方法,每个元素都将实现该方法:
enum State
{
A{
public void void doSomeWork(State state){
switch(state){
case A:
case B:
...
}
}
},
B,
C,
D
abstract void doSomeWork(State state);
}
然后您的方法可以如下所示
void doWork(MyObject o1, MyObject o2){
o1.state.doSomeWork(o2.state);
}
仅使用两种状态组合,嵌套开关可能是实现和理解以下内容的最快方法:
switch (o1.state) {
case X: switch(o2.state) { }
//..etc
}
如果案例顺序与某些组合无关,您可以在这些案例中交换o1
和o2
,然后将它们放入开关
(并避免重复代码)。此外,对于具有相同行为的所有案例组合,您可以利用fall-through行为
最后,以这种方式实现它可能会使这些组合的实际情况更加明显,这样您就可以实现更智能的方法。是的,它被称为。重要的是只有一个状态可以定义行为,即您可能需要将object1.state和object2.state组合成元状态。向statecontext注册此元状态,以便在Myobject.state更改时更新元状态
interface MyObjectStates {
void doWork(MyObject o1, MyObject o2);
}
class MyObjectStatesAA implements MyObjectStates {
void doWork(MyObject o1, MyObject o2) {
// do dowork for both states A
}
class MyObjectStatesBB implements MyObjectStates {
void doWork(MyObject o1, MyObject o2) {
// do dowork for both states B
}
// etc
然后,您需要在statecontext中保存一个MyObjectState对象,并在MyObject.state发生更改时更新它。您甚至可以一起删除状态枚举。如果你觉得这个方法很有趣,请给我一个便条,如果你喜欢,我会详细说明
状态模式的优点是,您不需要保存和读回枚举,也不需要相应地选择不同的代码路径,而是为每个要以不同方式处理的状态提供单独的代码。解决问题的OO解决方案是状态模式。它涉及到用状态对象封装状态交替条件。您可能会找到有关模式和的更多信息。顺便说一下,如果你还没有这本书,我强烈建议你买它
干杯 @org.life.java:胡说八道-使用==对枚举是完全安全的。@Michael Borgwardt我很抱歉,删除注释也是为了同样的场景
=
更可取,从中了解到这是唯一真正摆脱条件语句的解决方案-switch/case仍然是一个丑陋的条件语句(除非您正在编写解析器)。