1

我正在实现一些通用组件,我只是想知道我的设计模式是否有意义以及是否可以进行任何改进。例如,这是一个可用于过滤内容的通用面板:

/**
 * 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 方法,这有点烦人。有没有更好的方法来实现对该对象的引用?这是否是在检票口中实现可重用和相对通用组件的一种明智的方式?任何反馈将不胜感激,我相信这里还有改进的余地。

编辑我:只是在某些情况下,我正在做的是实现这样的页面

在此处输入图像描述

我向用户展示了一个数据视图和过滤它的选项。有很多不同实体的页面,但是 GUI 组件可以而且应该尽可能通用,以免违反 DRY。示例代码显然是页面的过滤器文本字段和按钮部分。

编辑二:如果可能的话,我希望这个组件更加松散耦合,例如让它能够做完全不同的事情,而不仅仅是修改一个 params 对象(例如,有另一种情况我需要更新两个 params 对象,然后我将无法使用此面板)。现在表单中的 onSubmit 方法需要对要在覆盖方法中使用的对象的引用是事先已知的。有没有办法不这样或动态设置这些对象的存在和/或类型?

编辑三:关键是这个面板的核心功能真的只是让用户

  • 输入一个字符串
  • 当用户单击按钮时,通知并授予系统其他部分对该字符串的访问权限。

“系统的其他部分”对字符串所做的事情不应该真正关心这个面板,但就像现在一样,它与“系统的其他部分”必须执行某些操作的 params 对象耦合。如果可能的话,我想摆脱这种耦合。我可能还想使用此面板中的字符串仅打印到控制台或将其用于其他一些任意任务。

4

3 回答 3

3

您可以使用类的构造函数来设置对象。

如果您让paramsObject使用 Java 泛型(因此得名:)),则更通用的方法是。您可以对实体进行超类化或让它们实现接口。

于 2011-12-14T06:20:48.937 回答
2

我在一个使用 Wicket 的 Web 应用程序上工作了 3 年多(开始使用 1.3.x,现在低于 1.4.x,并计划在几周内升级到 1.5.x)。您使用的方法是我们内部使用的方法。我们经常使用抽象类来表示常见的面板。我们唯一要做的就是 rotsch 在他的回答中所说的,我们使用很多泛型来尽可能地推断类型参数。

于 2011-12-14T06:48:40.360 回答
0

实际上,即使我一开始并没有意识到这一点,只需这样做就可以很容易地实现:

/**
 * 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);
        }
    });

这样我们就不需要发送对任何对象的任何引用(例如,需要使用 AJAX 进行更新的 params 对象或 wicket 组件),我们可以将这个面板重新用于我们想要的任何东西!

于 2011-12-14T07:30:39.377 回答