我正在实现一些通用组件,我只是想知道我的设计模式是否有意义,以及是否有任何改进可做。例如,这里有一个通用面板,可用于过滤内容:
/**
* 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方法,这是一种恼人的做法。是否有更好的方法来实现对该对象的引用?这是在wicket中实现可重用和相对通用的组件的一种通用方法吗?任何反馈都将是非常感谢的,我相信这里还有改进的余地。
编辑I:只是为了一些上下文,我所做的是实现这样的页面

在这里,我向用户提供一个数据视图和筛选它的选项。有很多不同实体的页面,但是GUI组件可以并且应该尽可能地泛化,以免违反DRY。示例代码显然是页面的筛选器、文本字段和按钮部分。
编辑二:如果可能的话,我希望这个组件能够更松散地耦合,例如,使它能够完成完全不同的事情,而不仅仅是修改一个params对象(例如,在另一个情况下,我需要更新两个params对象,那么我就不能使用这个面板)。表单中的onSubmit方法现在需要对overriden方法中使用的对象的引用是事先知道的。有没有办法不这样做,或者动态地设置这些对象的存在和/或类型?
编辑三:关键是这个面板的核心功能实际上是只允许用户
“系统的其他部分”对字符串所做的事情不应该真的涉及到这个面板,但是就像现在一样,它被耦合到“系统的另一部分”必须在其上执行某些操作的params对象。如果可能的话,这就是我想要摆脱的耦合。我可能还想使用这个面板中的字符串来打印控制台,或者使用它来执行其他任意任务。
发布于 2011-12-14 07:30:39
实际上,即使我一开始没有意识到这一点,但只要简单地这样做,就可以很容易地做到这一点:
/**
* 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对象或wicket组件,这些组件需要被用于AJAX更新),而且我们可以任意重用这个面板!
发布于 2011-12-14 06:20:48
您可以使用类的构造函数来设置对象。
如果允许paramsObject使用Java (因此名为:),将是一种更通用的方法。您可以对实体进行超类,也可以让它们实现接口。
发布于 2011-12-14 06:48:40
我在一个使用Wicket的web应用程序上工作了3年多(开始使用1.3.x,现在在1.4.x下,并计划在几周内升级到1.5.x )。您正在使用的方法是我们内部使用的方法。我们经常使用抽象类来表示公共面板。我们所做的唯一的事情就是罗奇在他的回答中所说的,我们使用了大量的泛型来尽可能多地推断类型参数。
https://stackoverflow.com/questions/8499903
复制相似问题