Шаблон дизайна универсальных компонентов калитки - PullRequest
1 голос
/ 14 декабря 2011

Я внедряю некоторые общие компоненты, и мне просто интересно, имеют ли смысл мои шаблоны проектирования и есть ли какие-либо улучшения, которые могут быть сделаны.Например, вот общая панель, которую можно использовать для фильтрации содержимого:

/**
 * Abstract class for textfields used for filtering. When overriding abstract method onUpdateFilter, the first thing
 * that must be done is to set the paramsobject, or else filtering wont work.
 * @author fred
 *
 */

public abstract class FilterFormPanel extends Panel {

    private static final long serialVersionUID = 1L;
    private FilterForm filterForm;
    private Object paramsObject; //this is object because paramsobjects differ depending on entity type

    public FilterFormPanel(String id) {
        super(id);
        filterForm = new FilterForm("filterForm");
        add(filterForm);
    }

        public String getFilterString(){
        return filterForm.getFilterString();
    }

    public void setParamsObject(Object paramsObject){
        this.paramsObject = paramsObject;
    }

    /**
     *For developers to implement in class that contains the correct references to params and facade objects, dataviews etc.
     *e.g. they could do params.setFilter(<reference to an instance of this class>.getFilterString() and ajax stuff too) 
     */
    public abstract void onUpdateFilter(AjaxRequestTarget target, Object paramsObject);

    private class FilterForm extends Form<Void> {

        private static final long serialVersionUID = 1L;
        private transient String filterString;

        public FilterForm(String id) {
            super(id);
            final TextField<String> filterTextField = new TextField<String>("filterTextField", new PropertyModel<String>(this, "filterString")); //textField for user to enter filter string
            add(filterTextField);

            add(new AjaxButton("filterButton") { //button to click for performing overriden method
                private static final long serialVersionUID = 1L;
                @Override
                protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                    onUpdateFilter(target, paramsObject);
                }
            }); 
        }

        public String getFilterString(){
            return filterString;
        }   
    }
}

Используется следующим образом в другом классе:

    filterFormPanel = new FilterFormPanel("filterFormPanel"){

        private static final long serialVersionUID = 1L;

        @Override
        public void onUpdateFilter(AjaxRequestTarget target, Object paramsObject) {
            filterFormPanel.setParamsObject(params);
            params.setFilterString(filterFormPanel.getFilterString());
            //ajax stuff
            target.addComponent(dataViewContainer);
            nav.setVisible(dataProvider.size()!=0);
            target.addComponent(nav);
            emptyLabel.setVisible(dataProvider.size()==0);
            target.addComponent(emptyLabel);
        }

    };

    settingsContainer.add(filterFormPanel);

Это раздражает то, что вы вынуждены использоватьМетод setParamsObject первым делом переопределяет метод.Есть ли лучший способ получить ссылку на этот объект?И это вообще нормальный способ реализации повторно используемых и относительно общих компонентов в калитке?Любая обратная связь будет принята с благодарностью, я уверен, что здесь есть возможности для улучшения.

РЕДАКТИРОВАТЬ I: Просто для некоторого контекста я делаю, что я реализую такие страницы

enter image description here

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

РЕДАКТИРОВАТЬ II: Я хочу, чтобы этот компонент был еще более свободно связан, если это возможно, например, чтобы он мог выполнять совершенно разные вещи, а не просто изменятьобъект params (например, есть другой случай, когда мне нужно обновить два объекта params, тогда я не смогу использовать эту панель).Метод onSubmit в том виде, в каком он есть сейчас, требует ссылки на объекты, которые будут использоваться в переопределенном методе, которые известны заранее.Есть ли какой-либо способ не использовать его таким образом или динамически устанавливать наличие и / или типы этих объектов?

РЕДАКТИРОВАТЬ III: Дело в том, что основная функция этой панели на самом деле заключается только в том, чтобы позволить пользователю

  • введите строку
  • уведомите и предоставьте доступ к этой строке какой-либо другой части системы, когда пользователь нажимает кнопку.

Что это "другоечасть системы, связанная со строкой, на самом деле не должна касаться этой панели, но, как и сейчас, она связана с объектом params, над которым «другая часть системы» должна выполнить какую-то операцию.Именно от этой связи я бы хотел избавиться, если это возможно.Я мог бы также использовать строку из этой панели для простой печати на консоль или использовать ее для какой-либо другой произвольной задачи.

Ответы [ 3 ]

3 голосов
/ 14 декабря 2011

Вы можете использовать конструктор класса для установки объекта.

Более общий подход был бы, если вы позволите paramsObject использовать универсальные элементы Java (отсюда и название :)).Вы можете переклассифицировать сущности или позволить им реализовать интерфейс.

2 голосов
/ 14 декабря 2011

Я работаю более 3 лет над веб-приложением, использующим Wicket (начал использовать 1.3.x, сейчас под 1.4.x и планирую обновить до 1.5.x через несколько недель). Подход, который вы используете, - тот, который мы используем внутри компании. Мы часто используем абстрактные классы для представления общих панелей. Единственное, что мы делаем, - это то, что Ротш сказал в своем ответе: мы используем множество обобщений, чтобы вывести как можно больше аргументов типа.

0 голосов
/ 14 декабря 2011

На самом деле, хотя я сначала не осознавал этого, этого можно было легко достичь, просто выполнив следующее:

/**
 * Abstract class for textfields used for filtering.
 * @author fred
 *
 */

public abstract class FilterStringPanel extends Panel {

private static final long serialVersionUID = 1L;
private FilterForm filterForm;

public FilterStringPanel(String id) {
    super(id);
    filterForm = new FilterForm("filterForm");
    add(filterForm);
}

public String getFilterString(){
    return filterForm.getFilterString();
}

/**
 *For developers to implement in class that contains the correct references to params and facade objects, dataviews etc.
 *e.g. they could do params.setFilter(<reference to an instance of this class>.getFilterString() and ajax stuff too) 
 */
public abstract void onUpdateFilter(AjaxRequestTarget target);

private class FilterForm extends Form<Void> {

    private static final long serialVersionUID = 1L;
    private transient String filterString;

    public FilterForm(String id) {
        super(id);
        final TextField<String> filterTextField = new TextField<String>("filterTextField", new PropertyModel<String>(this, "filterString")); //textField for user to enter filter string
        add(filterTextField);

        add(new AjaxButton("filterButton") { //button to click for performing overriden method
            private static final long serialVersionUID = 1L;
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                onUpdateFilter(target);
            }
        }); 
    }

    public String getFilterString(){
        return filterString;
    }   
}
}

И затем реализовав его следующим образом:

    settingsContainer.add(new FilterStringPanel("filterStringPanel"){
        private static final long serialVersionUID = 1L;
        @Override
        public void onUpdateFilter(AjaxRequestTarget target) {
            params.setFilterString(getFilterString());
            target.addComponent(dataViewContainer);
            nav.setVisible(dataProvider.size()!=0);
            target.addComponent(nav);
            emptyLabel.setVisible(dataProvider.size()==0);
            target.addComponent(emptyLabel);
        }
    });

Таким образом, нам не нужно отправлять какие-либо ссылки на какие-либо объекты (например, объекты params или компоненты калитки, которые должны быть предназначены для обновления с помощью AJAX), и мы можем повторно использовать эту панель для всего, что нам нужно!

...