Java 在枚举中重写抽象方法时避免代码重复

Java 在枚举中重写抽象方法时避免代码重复,java,enums,state,state-machine,code-duplication,Java,Enums,State,State Machine,Code Duplication,我正在用Java用enum实现一个状态机。下面我有一个玩具示例,其中我根据组成员身份在X、Y和Z状态之间转换 问题是,Y和Z的转换规则是相同的(即覆盖的方法是相同的) 这里有没有避免代码重复的方法?在我的实际例子中,情况更为严重,因此代码复制的可能性更大 enum Group { A,B,C } enum Element { X(Group.A) { @Override public Element getNextElement(Element

我正在用Java用enum实现一个状态机。下面我有一个玩具示例,其中我根据组成员身份在
X
Y
Z
状态之间转换

问题是,
Y
Z
的转换规则是相同的(即覆盖的方法是相同的)

这里有没有避免代码重复的方法?在我的实际例子中,情况更为严重,因此代码复制的可能性更大

enum Group {
    A,B,C
}

enum Element {
    X(Group.A) {
        @Override
        public Element getNextElement(Element nextElement) {
            if(nextElement.getGroup() == Group.B) {
                return nextElement;
            } else {
                return this;
            }
        }
    },
    Y(Group.B) {
        @Override
        public Element getNextElement(Element nextElement) {
            if(nextElement.getGroup() == Group.A) {
                return nextElement;
            } else {
                return this;
            }
        }
    },
    Z(Group.C) {
        @Override
        public Element getNextElement(Element nextElement) {
            if(nextElement.getGroup() == Group.A) {
                return nextElement;
            } else {
                return this;
            }
        }
    };

    Group group;

    Element(Group group) {
        this.group=group; 
    };

    public Group getGroup() {
        return this.group;
    }

    public abstract Element getNextElement(Element nextElement);

}
您可以使用,大致如下面的示例所示。通过思考不同策略之间的相互关系,并将相似性引入一个或多个策略基类,可以改进该示例:

enum Element {

    interface TransitionStrategy {
       Element getNextElement (Element myself, Element nextElement);
    }

    static class NextOnBStrategy implements TransitionStrategy {
       Element getNextElement (Element myself, Element nextElement) {
            if(nextElement.getGroup() == Group.B) {
                return nextElement;
            } else {
                return myself;
            }
        }                
    }

    // other strategies

    X(Group.A, new NextOnBStrategy ()),
    Y(Group.B, new NextOnAStrategy ()),
    Z(Group.C, new NextOnAStrategy ());

    Group group;
    TransitionStrategy strategy;

    Element(Group group, TransitionStrategy strategy) {
        this.group=group; 
        this.strategy=strategy;
    };

    // ...


    public Element getNextElement(Element nextElement) {
       return this.strategy.getNextElement (this, nextElement);
    }

}

假设您的逻辑除了转换规则中的值之外是相同的,您可以通过以下方式进行参数化:

enum Element {
    X(Group.A, Group.B),
    Y(Group.B, Group.A),
    Z(Group.C, Group.A);

    private final Group group;
    private final Group nextGroup

    private Element(Group group, Group nextGroup) {
        this.group = group; 
        this.nextGroup = nextGroup;
    }

    public Group getGroup() {
        return this.group;
    }

    public Element getNextElement(Element nextElement) {
        return nextElement.getGroup() == nextGroup ? nextElement : this;
    }
}
您仍然可以在某些值中覆盖
getNextElement
。例如:

enum Element {
    X(Group.A, Group.B) {
        @Override public Element getNextElement(Element nextElement) {
            return someRandomCondition ? nextElement : this;
        }
    }
    Y(Group.B, Group.A),
    Z(Group.C, Group.A);

    // Other code as above
}

这取决于管理转换条件所需的复杂性,一个好的面向目标的方法是封装规则,例如:

class RuleSet {
  Map<Element, List<Rule>> rules = new HashMap<Element, List<Rule>>();

  void addRule(Element element, Rule rule) {
    List<Rule> rulesOfElem = rules.get(element);
    if (rulesOfElem == null) {
      rulesOfElem = new ArrayList<Rule>();
      rules.put(element, rulesOfElem);
    }

    rulesOfElem.add(rule);
  }

  Element evaluate(Element element, Environment env) {
    List<Rule> rulesOfElem = rules.get(element);
    if (rulesOfElem != null) {
      for (Rule rule : rulesOfElem) {
        Element next = rule.evaluate(element, env);
        if (next != null) return next;
      }
    }

    return element;
  }
}

abstract class Rule {
  Element evaluate(Element current, Environment env);
}

class GroupRule extends Rule {
  private final Group from, to

  GroupRule(Group from, Group to) {
    this.from = from;
    this.to = to;

    for (each Element in Group)
      ruleSet.add(element, this);
  }

  Element evaluate(Element element, Environment env) {
    ...
  }
}
类规则集{
映射规则=新建HashMap();
void addRule(元素、规则){
List rulesOfElem=rules.get(元素);
如果(RulesOffelem==null){
RulesOffelem=新的ArrayList();
规则。放置(元素,规则元素);
}
规则要素添加(规则);
}
元素评估(元素、环境环境){
List rulesOfElem=rules.get(元素);
如果(RulesOffelem!=null){
for(规则规则:RulesOffelem){
元素下一步=规则。评估(元素,环境);
如果(next!=null)返回next;
}
}
返回元素;
}
}
抽象类规则{
元素评估(元素当前、环境环境);
}
类GroupRule扩展了规则{
私人最终组从,到
GroupRule(组从、组到){
this.from=from;
这个;
对于(组中的每个元素)
添加(元素,this);
}
元素评估(元素、环境环境){
...
}
}

但是,如果不知道所需的复杂性,就很难决定是保持简单还是保持可维护性更好。

要决定下一个状态,您需要做什么样的检查?