один метод классов с перечислением в Java - PullRequest
3 голосов
/ 01 октября 2009

У меня есть enum, который выглядит как

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);
}

Теперь я думаю, что мы все можем согласиться, что это выглядит ужасно? но что будет лучше? Я мог бы иметь абстрактную фабрику, но тогда мне потребовалось бы три класса реализации, каждый из которых представлял собой однострочный метод. Не найти это так красиво, либо. Я мог бы использовать переключатель (или в коде или в перечислении). Но тогда я мог бы забыть добавить дело.

Итак, какой путь? Должен быть образец для этого, но, кажется, не могу найти тот. Лучшее, что я могу придумать, - это добавлять комментарии к автоколлапсу в Netbeans, хотя и не так блестяще.

Ответы [ 3 ]

8 голосов
/ 01 октября 2009

Решение состоит в том, чтобы создать приватный конструктор для перечисления:

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] Обратите внимание, что вы можете передавать более сложные вещи. Например, вы можете передать класс, который реализует определенный интерфейс (скажем, Work, у которого есть метод doWork()). Таким образом, вы можете хранить вызовы методов в перечислениях для выполнения различных видов работы.

Проверьте шаблон команды или, возможно, шаблон стратегии .

3 голосов
/ 01 октября 2009

Это некрасиво, но большинство решений нетривиальных расширений проблемы просто собирается устранить уродство.

Например, вы можете инкапсулировать три различных поведения в трех различных реализациях некоторого интерфейса, а затем передать различные реализации поведения конструктору каждого перечисления. (Это в основном командный или стратегический подход, который предлагают другие).

Если вы сделаете эти реализации и интерфейс отдельными классами, то вы потенциально можете разоблачить это поведение за пределами перечисления, что является ненужным и, возможно, уродливым.

Если вы сделаете их закрытыми статическими внутренними классами перечисления, вы перенесете безобразие из верхней части файла в нижнюю часть файла. Насколько менее уродливо это в глазах смотрящего.

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;
        }
    }
}

Другое очевидное решение состоит в том, чтобы поместить все три поведения в качестве закрытых методов и добавить switch(this) в открытый метод. Лично я считаю это безобразным грехом, но многим бывшим программистам, похоже, это нравится. :)

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;
    }
}
1 голос
/ 01 октября 2009

А как же?

     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;
        }
      }

Даже если ваш реальный материал более сложный, есть несколько методов, которые позволяют такие улучшения. Пожалуйста, напишите ваши реальные потребности ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...