Java 在枚举中重写抽象方法时避免代码重复
我正在用Java用enum实现一个状态机。下面我有一个玩具示例,其中我根据组成员身份在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
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);
}
元素评估(元素、环境环境){
...
}
}
但是,如果不知道所需的复杂性,就很难决定是保持简单还是保持可维护性更好。要决定下一个状态,您需要做什么样的检查?