2013-08-25 2 views
2

Я не могу понять, как избежать параллельных иерархий на практике. например Рассмотрим приложение, которое должно создавать/сохранять/редактировать заметки на разных уровнях, это приложение на основе java swing.Являются ли параллельные иерархии наследования запахом кода?

домен Иерархия:

AbstractNote < MonthNote 
      < DayNote 
      < ProductNote 

только для чтения Просмотра иерархии (как показан на JTabPane, каждый из которых JTable показать конкретные детали примечания)

AbstractNotePanel < MonthNotePanel 
        < DayNotePanel 
        < ProductNotePanel 

отмечает редактор иерархию (отображается при нажатии пользователя на на конкретное примечание в строке таблицы.

AbstractNoteEditorDialog < MonthNoteEditorDialog 
          < DayNoteEditorDialog 
          < ProductNoteEditorDialog 

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

Я вполне доволен своим дизайном, поскольку большая часть общего кода находится в абстрактном классе (применяя шаблон шаблона метода там). В случае, если мне нужно создать новый тип примечания, например. YearNote, тогда мне нужно параллельно создавать YearNotePanel и YearNoteEditorDialog, что вполне приемлемо для меня, потому что мне не нужно много кода из-за шаблонов. Прежде всего, я хочу избежать запаха кода в моем дизайне. Пожалуйста, предложите мне альтернативный дизайн в приведенном выше сценарии, чтобы мой код был еще модульным. Thanks

+0

С чего начинается разница между MonthNote, DayNote и ProductNote? –

+0

Они немного отличаются друг от друга и могут быть ОЧЕНЬ разными в будущем. Каждая заметка привязана к пользователю и имеет длинный текст. MonthNOte и DayNote имеют joda MonthYear и LocalDAte соответственно. В примечании к продукту нет информации о дате, вместо этого у него есть экземпляр продукта (другой объект домена), мы просто показываем имя продукта на ui. – Joe

+0

избавиться от них ** не ** расширяя JSomething, когда-либо - они предназначены для использования как есть – kleopatra

ответ

1

Говорить «прежде всего, я хочу, чтобы избежать запаха кода в моем дизайне» является похвальной целью, но всегда имейте в виду, что the core of design is to weigh costs.

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

Уровень пользовательского интерфейса читает эту конфигурацию, а затем создает пользовательский интерфейс. Это означает, что мой дизайн выглядит так:

AbstractNote < MonthNote 
      < DayNote 
      < ProductNote 

NotePanel 
NoteEditorDialog 

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

Кроме того, если я добавлю функцию/исправлю ошибку в слое пользовательского интерфейса, вероятность того, что я сломаю что-то в другом месте, намного выше, поэтому изменение кода, чтобы сделать редактирование DayNote более удобным может сломать MonthNote).

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

+0

Спасибо Аарону за ваш ответ, и я согласен с балансированием противоречащих целей для обеспечения экономической эффективности и простоты обслуживания. Общий NotePanel и NoteEditorDialog, основанный на чем-то вроде конфигурации аннотации, может привести к запаху кода оператора или циклической сложности, что будет очень сложно поддерживать. Пожалуйста, поправьте меня, если я ошибаюсь. Вместо этого я предпочел бы полиморфизм. – Joe

+0

Я не использую инструкции switch. Мой интерфейс - это сетка. Пока я читаю конфигурацию, я создаю разные элементы редактора, и каждый редактор знает, что делать без каких-либо переключателей. Затем загруженная конфигурация помещает редактор в каждую ячейку сетки (некоторые редакторы - это просто метки). –

0

Важным API, который вы можете использовать здесь, является BeanInfo API. Познакомиться с этим. В любом классе java (bean) вы можете определить класс BeanInfo метауровня.

Одно из использования заключается в том, что таким образом вы можете создать новый компонент Swing, а в среде IDE, используя BeanInfo, обеспечите свойства компонента таблицы. (В среде IDE NetBeans вы можете добавить свои собственные компоненты в палитры компонентов и работать таким образом.) Это касается редакторов свойств (для выбора цвета/данных/..).

+0

Благодаря Joop. Честно говоря, я никогда не использовал API BeanInfo. Также я всегда хочу, чтобы мои решения не привязывались ни к какой IDE. Есть ли способ использовать BeanInfo без какой-либо IDE? – Joe

+0

BeanInfo - это стандарт, описывающий свойства «бобов», классов. Таким образом, это было i.a. предназначенные и принятые несколькими IDE. Но он совершенно не зависит от какого-либо варианта использования. В вашем случае общее описание полей может быть проще. Хотя по аннотациям, хотя по XML, ... или BeanInfo. –

Смежные вопросы