Замена для огромных случаев - PullRequest
6 голосов
/ 21 февраля 2012

Я пытаюсь улучшить проект Java, который использует много больших операторов case. В случаях, когда используется оператор case, он используется для обработки события, с которым связан атрибут. Например:

public void jumpOverWall(int wallID) {
    switch (wallID) {
            case 0:
            case 1213:
            case 2123:
            case 3123:
            case 4123:
    }
}

Числа не являются последовательными и для всех необходимо выполнить другое действие - например, сказать «Вы не можете перепрыгнуть через эту стену» или переместить персонажа в заданное положение. Есть очень немного случаев, в которых ответ случая следует за установленным образцом. Под этим я подразумеваю, что операторы switch не следуют шаблону, который допускал бы код, подобный следующему:

public void jumpOverWall(int wallID) {
    someArray[1213] = 10;
    someArray[3123] = 20;

    if (playerJumpingSkill > someArray[wallID]) {
            // Do something
    } else {
            sendPlayerMessage("You cannot do this!");
    }
}

Поэтому мне интересно, как лучше всего справиться с этими «событиями». Вся идея системы стилей «обработчик событий» мне нравится, но я застрял в том, как ее реализовать (или лучшее решение проблемы). Слишком много «событий» (по моему мнению), чтобы иметь отдельный класс для каждого.

Есть ли метод / дизайн для перехвата событий? Будет ли это применимо / работа. Я бы искал метод легкой зацепки, такой как:

hookEvent(1213, new SomeInterface() {
    boolean eventOK() {
        // Do something
        return true;
    }
}

Тогда эти «крючки» будут проверены и вызваны?

Ответы [ 3 ]

4 голосов
/ 21 февраля 2012

Шаблон команды может быть лучшим вариантом для вас. Скажем, у вас есть объект команды реализации Интерфейс:

public Interface Command {
      void processEvent(Event e);
}

Тогда вы можете иметь несколько хеш-команд, обозначаемых кодами событий - гораздо более удобочитаемыми. И вы даже можете использовать DI-контейнер (Spring является самым популярным, но есть также Picocontainer или Google Guice, и, конечно, я пропустил некоторые) для создания объектов команд - просто зарегистрируйте соответствующие объекты с ключами в качестве кодов событий. Это сохранит ваш код для заполнения хеша.

И даже не должно быть много предложений - это могут быть просто по-разному сконфигурированные экземпляры (в зависимости от вашего варианта использования) - сегодня нет разоблачения классов

2 голосов
/ 21 февраля 2012

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

public void jumpOverWall(int wallID)
{
      switch (wallID) 
        {
        case 0:     methodA(wallID); break; // you could of course have a more descriptive name here.
        case 1213:  methodB(wallID); break; 
        case 2123:  methodC(wallID); break;
        case 3123:  methodD(wallID); break;
        case 4123:  methodE(wallID); break;
        }
}
1 голос
/ 21 февраля 2012

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

Слишком много 'событий', чтобы иметь отдельный класс для каждого.

Так как вам все равно нужен другой код, используя классыне взрывает твой код.

В качестве альтернативы вы можете использовать Перечисления с реализациями методов, специфичными для констант :

public enum WallID {
1213 { returnType jumpOverWall(Wall wall){ //... 
  } },
3213 { returnType jumpOverWall(Wall wall){ //...
  } },
1332 { returnType jumpOverWall(Wall wall){ //...
  } },

//you can also use better names for your constants ;)

abstract returnType jumpOverWall(Wall wall);
}

Вы можете подробно прочитать, как это работает, и почему вы должны отдавать предпочтения перечислениямваши int-идентификаторы (поскольку они действительно являются чисто идентификаторами) в Effective Java Джоша Блоха, 2-е издание , Item 30 (используйте перечисления вместо int-констант).

Обновление:

Используя один из этих двух подходов вместо идентификаторов int и оператора switch, вы получаете несколько преимуществ:

  • более модульная аппроксимация, следовательно, более читабельная и следующая SRP
  • более многократно используемая,Например, если вы хотите унаследовать какое-либо поведение jumpOverWall
  • , вы можете связать дополнительные данные с каждой константой
  • , вы можете предоставить дополнительные методы для констант, опять-таки, специфичные для констант, если вам нравится
  • и что я считаю наиболее важным: безопасность благодаря использованию системы типов Java и динамической диспетчеризации.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...