Всем привет!
Сначала предыстория. Всё дело идёт в вебе, но это не столь важно.
Допустим, есть класс Dialog — окошко. У нас есть 3 типа отображения (не просто стилизация CSS, а даже разная структура HTML — это действительно требуется).
Сейчас код разных методов (buildDialogHtml(), getCssClass() и т. д.) представляют собой ветвистые if'ы:
protected buildDialogHtml() {
if (ui == 0)
this.buildDialogHtmlType0();
else if (ui == 1)
this.buildDialogHtmlType1();
else
this.buildDialogHtmlType2();
Парадигма ООП говорит, что такой код можно и нужно разделить на иерархию классов:
- Dialog
- DialogType0
- DialogType1
- DialogType2
OK, делаем приватный конструктор, публичный фабричный метод create(), который и возвращает нам инстанс нужного класса.
Всё бы ничего, но у нас вот была такая иерархия:
- ABaseDialog (lib)
- VeryCustomUserDialog (user)
- Dialog (lib)
- MessageDialog (lib)
- StandardUserDialog (user)
Как видите, получается, мы не можем вклиниться нашим ООП в такую структуру. Т. е. такое ветвление классов подходит только когда тип UI является гарантированно последним звеном в иерархии.
Как реализовать такую штуку, чтобы было красиво и расширяемо?
Может есть какой-то паттерн? Пока на ум приходит только паттерн делегата: создание какого-то объекта UIType внутри Dialog, которому и делегируются данные методы. Но это плодит кучу кода, навигация по которому так себе, и кажется, что уж лучше if'ы. Кроме того ведь пользователь нашей библиотеки может случайно переопределить метод, который вызывает делегата, и не будет понимать, почему всё сломалось (или сломалось только на конкретном типе UI).