I've been working on software architecture refactoring for last couple weeks. During a workshop one of architects showed me an interesting approach.
We were applying MVP-like style and then faced with the question: How a Presenter should tell a View to change its state?
Brute force approach looks like following:
public class Presenter {Well, this is actually ok, but the more components you have on the form, more verbose View interface becomes.
private View view;
public void doSomething() {
//Here, services are processing something really important
view.setTitle( "Updated" );
view.setName( "New name" );
}
}
public class Form extends JFrame implements View {
private JTextfield nameTf;
@Override
public void setTitle( String title ) {
setTitle( title );
}
@Override
public void setName( String name ) {
nameTf.setText( name );
}
}
The move I am talking above is encapsulating a setter into separate object. Look here:
public abstract class ValueSetter {Now it is possible to write more elegant code:
private static Map<Class<?>, ValueSetter> SETTERS;
static {
SETTERS = new HashMap<Class<?>, ValueSetter>();
SETTERS.put(JTextField.class, new JTextFieldSetter());
}
public static ValueSetter get( Class<?> type ) {
if( SETTERS.containsKey(type) ) {
return SETTERS.get(type);
}
throw new IllegalArgumentException( "Missing ValueSetter for " + type );
}
public abstract void set( Object target, Object value );
private static class JTextFieldSetter extends ValueSetter {
@Override
public void set(Object target, Object value) {
((JTextField)target).setText( (String) value );
}
}
private static class JFrameSetter extends ValueSetter {
@Override
public void set(Object target, Object value) {
((JFrame)target).setTitle( (String) value );
}
}
}
public class Form extends JForm implements View {So thanks Marcin for this nice tip and fresh idea for me ;)
private Map<String, JComponent> components;
@Override
public void updateComponent(String id, Object value) {
JComponent component = components.get(id);
ValueSetter.get(component.getClass()).set(component, value);
}
}