An attempt to extend an enum to prevent branching without violating the Open-Closed principle I love making utility State enums, and giving them methods that do useful things based on which instance of the enum is provided. This works when the enum is very specific to the class I'm working on, but can often make no sense when I need to switch on the enum type but I don't want the enum itself to know anything about that functionality. Further, I don't want to violate the open-closed principle in my main enum. I would prefer to avoid doing switch...case on the enum if possible.

Here's my solution that attempts to get the best of both worlds. It works (which is why I'm on CodeReview and not Programmers or SO), but it's clunky. Notice that I never have to change MyEnum again, all I do is create a new helper class each time I have a new behavior that I "wish" MyEnum had. Is there a better way?

public class EnumExample {
  public static interface OneEnumVisitor&lt;R, A&gt; {
    R visitFoo(A args);
    R visitBar(A args);
  }

  public static interface TwoEnumVisitor&lt;R, A, B&gt; {
    R visitFoo(A argOne, B argTwo);
    R visitBar(A argOne, B argTwo);
  }

  public static enum MyEnum {
    FOO {
      public &lt;R, A&gt; R visit(OneEnumVisitor&lt;R, A&gt; visitor, A args) {
        return visitor.visitFoo(args);
      }
      public &lt;R, A, B&gt; R visit(TwoEnumVisitor&lt;R, A, B&gt; visitor, A argOne, B argTwo) {
        return visitor.visitFoo(argOne, argTwo);
      }
    },
    BAR {
      public &lt;R, A&gt; R visit(OneEnumVisitor&lt;R, A&gt; visitor, A args) {
        return visitor.visitBar(args);
      }
      public &lt;R, A, B&gt; R visit(TwoEnumVisitor&lt;R, A, B&gt; visitor, A argOne, B argTwo) {
        return visitor.visitBar(argOne, argTwo);
      }
    };

    public abstract &lt;R, A&gt; R visit(OneEnumVisitor&lt;R, A&gt; visitor, A args);
    public abstract &lt;R, A, B&gt; R visit(TwoEnumVisitor&lt;R, A, B&gt; visitor, A argOne, B argTwo);
  }

  public static enum NewMethod implements TwoEnumVisitor&lt;Integer, Integer, Integer&gt; {
    INSTANCE;

    @Override
    public Integer visitFoo(Integer argOne, Integer argTwo) {
      return argOne.intValue() - argTwo.intValue();
    }

    @Override
    public Integer visitBar(Integer argOne, Integer argTwo) {
      return argTwo.intValue() + argOne.intValue();
    }
  }

  public static class SomeObject {
    private final MyEnum type;
    private final int param;

    public SomeObject(MyEnum type, int param) {
      this.type = type;
      this.param = param;
    }

    public int doMath(int value) {
      return type.visit(NewMethod.INSTANCE, value, param);
    }
  }

  public static void main(String... args) {
    SomeObject myObject = new SomeObject(MyEnum.FOO, 5);
    SomeObject myOtherObject = new SomeObject(MyEnum.BAR, 5);

    System.out.println(myObject.doMath(10));
    System.out.println(myOtherObject.doMath(10));
  }
}
It's really hard to tell which parts of your code are the problem you are trying to solve, and which parts are the example.  I think that's a hint that the solution has made things worse, rather than better.

Attempting to summarize your constraint - you want to use an enum to select the appropriate behavior to use at some point in the code, but you don't want to use a switch statement, and you don't want to have to modify the enum to achieve the new behavior.

If so, I think an EnumMap should serve nicely.

private static final EnumMap&lt;MyEnum, TwoArgFunction&lt;Integer,Integer,Integer&gt;&gt; lookup = new EnumMap&lt;MyEnum, TwoArgFunction&gt; (MyEnum.class);

static {
    lookup.put(MyEnum.FOO, new TwoArgFunction&lt;Integer,Integer,Integer&gt; () {
        Integer apply (Integer lhs, Integer rhs) {
            return lhs.intValue() - rhs.intValue();
        }
    ) ;

    lookup.put(MyEnum.BAR, new TwoArgFunction&lt;Integer,Integer,Integer&gt; () {
        Integer apply (Integer lhs, Integer rhs) {
            return lhs.intValue() + rhs.intValue();
        }
    ) ;
}

public static class SomeObject {
    ...
    public int doMath(int value) {
        return lookup.get(type).apply(value, param);
    }
}


If you really want to use a visitor based approach, you should probably refactor the abstract methods to an interface; which would allow you to extend the existing vocabulary of enums without actually needing to change MyEnum at all.

interface Visitable {
    public abstract &lt;R, A&gt; R visit(OneEnumVisitor&lt;R, A&gt; visitor, A args);
    public abstract &lt;R, A, B&gt; R visit(TwoEnumVisitor&lt;R, A, B&gt; visitor, A argOne, B argTwo);
}

public static enum MyEnum implements Visitable {
    FOO { ... },
    BAR { ... };
}

public static class SomeObject {
    private final Visitable&lt;Integer,Integer,Integer&gt; type;
    private final int param;

    public SomeObject(Visitable&lt;Integer,Integer,Integer&gt; type, int param) {
        this.type = type;
        this.param = param;
    }

    public int doMath(int value) {
          return type.visit(NewMethod.INSTANCE, value, param);
    }
}


Which in turn allows other programmers to introduce their own enums that can be used by SomeObject

public static enum HisEnum implements Visitable {
    BAZ {...}
}