Редактировать: у меня было чувство, что люди не верят, что это возможно или просто, поэтому я сделал это - заняло около часа с нуля - потребовалось бы 40 минут, если бы я просто использовал один метод как цель вместо того, чтобы отражать ее для разделения методов для каждого пункта меню.
Вот Протестированный исходный код . Это работает, но это один большой метод и уродливый - рефакторинг, если вы его используете. Я могу исправить это в течение следующих нескольких дней, я всегда хотел иметь копию этого, чтобы иметь возможность повторно использовать.
--- оригинальный пост
Прежде всего, не забудьте отделить ваш код от данных. Это означает, что вы никогда не должны печатать:
new Menu("File...");
Строка "Файл ..." является данными. Если вы начнете думать так, вы обнаружите, что ваш вопрос отвечает сам на себя.
Сначала вам нужно собрать некоторые данные. Вы должны получить «Файл ...» и «Сохранить» в меню. Я обычно начинаю со строкового массива (который вы можете легко переместить в файл)
new String[]{"File...","+Save","Load"...}
Это один из самых простых шаблонов, с которых я начинал. Затем вы можете разобрать знак + и использовать его для обозначения «Выпадающий уровень в меню при добавлении этого» * 1017 *
Это просто глупое соглашение, придумайте свое, если оно вам не нравится.
Следующий шаг - это привязка к коду для запуска. Вы могли бы заставить их всех вызывать один и тот же метод, но какая боль в заднице (оператор Giant switch). Одной из возможностей является использование отражения для привязки имени метода во время чтения данных. Вот одно из решений (опять же, оно может не соответствовать вашим вкусам)
new String[]{"File...[fileMenu]","+Save[saveMenu]","Load[loadMenu]"...}
Затем вы разбираете вещь в квадратных скобках, рефлексивно подключаете ее к методу в вашем текущем классе, и вы настроены.
В этот момент у меня всегда есть искушение, и я научился бороться с ним, потому что он НИКОГДА не срабатывает. Искушение состоит в том, чтобы использовать первый набор данных («Файл ...») и манипулировать им, чтобы он соответствовал некоторому шаблону и автоматически связывался с вашим кодом (в этом случае удалите все не-альфа-символы, сделайте первую букву строчной и добавьте «Меню», чтобы получить правильное имя метода). Не стесняйтесь попробовать это, это очень привлекательно и кажется гладким, но будьте готовы отказаться от него, когда он не удовлетворяет некоторой потребности (например, два пункта меню с одинаковым именем в разных подменю).
Другой способ - если ваш язык поддерживает замыкания, вы можете создать имя файла и замыкание в одном и том же месте.
В любом случае, как только вы начнете кодировать, как это, вы обнаружите, что ВСЕ ваше построение меню выполняется одним методом из 10 строк, и вы можете изменить его в соответствии со своими потребностями. У меня был случай, когда мне пришлось изменить набор меню на иерархию кнопок, и я сделал это за 2 минуты.
В конце концов, вы можете использовать этот шаблон, чтобы легко настроить объекты действий и изменить способ их использования (в одном месте, в одной строке кода), поэтому вы можете поэкспериментировать с ними. Есть много способов их использования, но если вы не сделаете то, что я рекомендую здесь, вам придётся перестраивать каждый пункт меню для каждого изменения, что действительно раздражает - после одного изменения вы потратил бы больше времени, чем если бы вы только что внедрили решение на основе данных.
Это на самом деле не сложный код, он может занять час или два, тогда вам никогда не придется писать новое Меню ("... опять. Поверьте мне, этот вид инструментов почти всегда стоит.
редактировать:
В наши дни я почти всегда управляю данными. Обычно я прототипирую несколько вещей обычным способом, распознаю шаблон и рефакторинг - и если вы выполняете рефакторинг правильно, данные почти всегда учитываются, а то, что у вас остается, прекрасно, сжато и легко обслуживаемо.
Я мог бы сделать то, что предложил выше, менее чем за полчаса (возможно, час, чтобы сделать отражающую версию). Это почти всегда так же долго, как если бы вы использовали незарегистрированную версию, и с тех пор ваши сбережения увеличиваются при каждом изменении.
Это очень похоже на то, что людям нравится в ruby, за исключением того, что с помощью ruby они, кажется, вставляют еще больше данных в свой код (что делает чрезвычайно сложным полное извлечение данных из кода, что всегда является хорошей целью для интернационализации ).
Хм, я уже говорил, что если вы умеете извлекать данные таким образом, i18n практически бесплатен?
Я предлагаю вам попробовать и посмотреть, что вы думаете. Встраивать элемент управления в строки не нужно, если вам неудобно. Я склонен использовать строковые / объектные массивы только потому, что их действительно легко вводить, они все еще находятся в файле, пока вы кодируете, и тривиальны для последующего извлечения, но если вам нравится YML или XML или файлы свойств, используйте все, что вам удобно с - просто абстрагируйте ваши данные от вашего кода!