Шаблон проектирования для обогащения класса новыми функциями

Я реализовал серию классов для управления поиском / подробной страницей с помощью JSF и PrimeFaces. Более подробно я создал абстрактный класс SearchDetailView<C extends BaseView, M> для того, чтобы централизовать общие функции для страницы поиска / детализации.

Короче, у меня есть класс MyView что расширяет базу SearchDetailView, Теперь я хотел бы добавить другое поведение MyView, то есть Confirm Dialog.

Мне интересно, какой шаблон дизайна я должен использовать? Я собирался использовать шаблон проектирования Decorator, но мне не нужно добавлять новое поведение во время выполнения, но я уже знаю, что такое поведение MyView необходимо.

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

Итак, я спрашиваю вас, какой шаблон проектирования добавляет поведение к классу?

На самом деле мой код выглядит следующим образом:

public abstract class SearchDetailView<C extends BaseController, M> extends BaseView {
    [...]
}

public abstract class ConfirmDialogDecorator<C extends BaseController, M> extends SearchDetailView<C, M> { 

    public void showDialog(final String message) { [...] }

}

public class MyView extends ConfirmDialogDecorator<MyController, MyModel> { 
    [...]
}

Но я хотел бы отделить ConfirmDialogDecorator от SearchDetailView, Любая идея? Благодарю.

ОБНОВЛЕНИЕ: Как предложено в двух ответах, я использовал стандартные методы Java 8 (шаблон Mixin?):

public interface ConfirmDialog {

    Dialog dialog = new Dialog();

    default public String getConfirmMessage() {
        return "Do you confirm?";
    }

    default String getWidgetVar() {
        return "confirmDialog";
    }

    public void onConfirm();

    default void showDialog(final String message) {
        dialog.setWidgetVar(this.getWidgetVar());
        dialog.setMessage(message);
        dialog.showDialog(message);
    }

    class Dialog {

        private String message;
        private String widgetVar;

        String getMessage() {
            return message;
        }

        void setMessage(final String message) {
            this.message = message;
        }

        public String getWidgetVar() {
            return widgetVar;
        }

        public void setWidgetVar(final String widgetVar) {
            this.widgetVar = widgetVar;
        }

        void showDialog(final String message) {
            final PrimeFaces current = PrimeFaces.current();
            current.executeScript("PF('" + this.widgetVar + "').show();");
        }
    }
}

public class MyView extends SearchDetailView<MyController, MyModel>
    implements ConfirmDialog {

    public void onSave() {
       if(!this.someCheck()) {
          this.showDialog("Are you really sure?");
       } else {
          this.save();
       }
    }

    @Override
    public void onConfirm() {
        this.save();
    }

    public void save() {
       // The save
    }

}

В xhtml:

<p:confirmDialog widgetVar="confirmDialog" global="true">
    <h:outputText value="#{myView.confirmMessage}" />
    <p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="pi pi-check" />
    <p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="pi pi-times" />
</p:confirmDialog>

2 ответа

Решение

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

а потом

Я хотел бы создать второй абстрактный класс, такой как ConfirmDialogDecorator, чтобы "динамически" добавить дополнительную функциональность.

Разве ты не говоришь что-то и наоборот?
Тот факт, что вы знаете возможности декорирования во время компиляции, не означает, что шаблон не адаптирован.

Но я бы хотел отделить ConfirmDialogDecorator от SearchDetailView.

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

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

Обычно для добавления функциональности в класс без наследования используется концепция mixim/trait.

Для реализации этой концепции вы можете использовать методы по умолчанию или стороннее программирование на Java.

Другие вопросы по тегам