Mikael Sundberg
Mikael Sundberg

Reputation: 783

one method classes with enum in java

I have an enum that looks like

public enum MyEnum
{
  myValue
  {
    @Override
    public String myMethod(String dostuff)
    {
      return dostuff + "One";
    }
  },
  myOtherValue
  {
    @Override
    public String myMethod(String dostuff)
    {
      return dostuff + "Two";
    }
  },
  aThirdValue
  {
    @Override
    public String myMethod(String dostuff)
    {
      return dostuff + "Three";
    }
  };

  public abstract String myMethod(String dostuff);
}

Now I think we can all agree that this looks horrible? but what would be the bether way? I could have an abstractfactory, but then i would need three implementationclasses that each as a one line method. Dont find that so pretty either. I could use a switch (either in the code or in the enum). But then i could forgett to add a case.

So, whats the way to go? There must be a pattern for this, but cant seem to find one. The best ive come up with so far is to add comments to autocollapse the methods in Netbeans, not so brilliant that either.

Upvotes: 3

Views: 702

Answers (3)

David Moles
David Moles

Reputation: 51153

It's ugly, but most solutions to non-trivial extensions of the problem are just going to move the ugliness around.

For instance, you could encapsulate the three different behaviors in three different implementations of some interface, and then pass a different behavior implementation to the constructor of each enum. (This is basically the command or strategy approach that others are suggesting).

If you make these implementations, and the interface, separate classes, then you've potentially exposed that behavior beyond the enum, which is unnecessary and arguably ugly.

If you make them private static inner classes of the enum, you've moved the ugliness from the top of the file to the bottom of the file. How much less ugly this is is in the eye of the beholder.

public enum Foo {

    ONE(new OneDelegate()), 
    TWO(new TwoDelegate()),
    THREE(new ThreeDelegate());

    // ////////////////////
    // Private stuff

    private final FooDelegate delegate;

    private Foo(FooDelegate delegate) {
        this.delegate = delegate;
    }

    // ////////////////////
    // Public methods

    public String doStuff(String stuff) {
        return delegate.doStuff(stuff);
    }

    // ////////////////////
    // Helper classes

    private static interface FooDelegate {
        String doStuff(String stuff);
    }

    private static class OneDelegate implements FooDelegate {
        @Override
        public String doStuff(String stuff) {
            return "One " + stuff;
        }
    }

    private static class TwoDelegate implements FooDelegate {
        @Override
        public String doStuff(String stuff) {
            return "Two " + stuff;
        }
    }

    private static class ThreeDelegate implements FooDelegate {
        @Override
        public String doStuff(String stuff) {
            return "Three " + stuff;
        }
    }
}

The other obvious solution is to put all three behaviors in as private methods, and put a switch(this) in the public method. Personally, I think this is ugly as sin, but a lot of ex-C programmers seem to like it. :)

public enum Foo {

    ONE, TWO, THREE;

    // ////////////////////
    // Public methods

    public String doStuff(String stuff) {
        switch(this) {
            case ONE:
                return doStuffOne(stuff);
            case TWO:
                return doStuffTwo(stuff);
            case THREE:
                return doStuffThree(stuff);

    // If we're handing all enum cases, we shouldn't need
    // a default (and per comments below, if we leave out
    // the default, we get the advantage that the compiler
    // will catch it if we add a new enum value but forget
    // to add the corresponding doStuff() handler

    //      default:
    //          throw new IllegalStateException("Who am I?");
        }
    }

    // ////////////////////
    // Static helpers

    private static String doStuffOne(String stuff) {
            return "One " + stuff;
    }

    private static String doStuffTwo(String stuff) {
            return "Two " + stuff;
    }

    private static String doStuffThree(String stuff) {
            return "Three " + stuff;
    }
}

Upvotes: 3

Aaron Digulla
Aaron Digulla

Reputation: 328724

The solution is to create a private constructor for the enum:

public enum MyEnum
{
  myValue("One"), myOtherValue("Two"), aThirdValue("Three");

  private String value;

  private MyEnum(String value) { this.value = value; }

  public String myMethod(String dostuff)
  {
    return dostuff + value;
  }
}

[EDIT] Note that you can pass more complex things in. For example, you can pass in a class which implements a certain interface (say Work which has a method doWork()). This way, you can store method calls in enums to do different kinds of work.

Check out the command pattern or maybe the strategy pattern.

Upvotes: 8

KLE
KLE

Reputation: 24169

What about?

     public enum MyEnum {
         myValue("One"),
         myOtherValue("Two"),
         aThirdValue("Three");

        private final String postfix;
        private MyEnum(String postfix) {
          this.postfix )= postfix;
        }
        public String myMethod(String dostuff) {
          return dostuff + postfix;
        }
      }

Even if your real stuff is more complex, there are several techniques that allow such improvements. Please post your real need...

Upvotes: 1

Related Questions