Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 重构if语句以使用适当的模式_Java_Oop_Design Patterns - Fatal编程技术网

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仍然是一个丑陋的条件语句(除非您正在编写解析器)。