Ho una casella di riepilogo con diversi elementi, che si tratti di server Web (tomcat, iis ecc.). Per ciascun valore della casella di riepilogo, l'interfaccia utente deve avere visualizzazioni diverse. Ad esempio, se scegliamo IIS, vengono visualizzati i campi del nome utente e della password. Se scegliamo tomcat, alcuni campi aggiuntivi appaiono a seconda del sistema operativo utente - IP e porta per linux e percorso per windows.
Il mio approccio attuale è il seguente: - Ho creato due enumerazioni. Il primo per sistemi operativi diversi (windows, linux, mac os x. Il secondo per server: iis, nginx, tomcat ecc. - Ho un metodo che restituisce il valore enum del sistema operativo. - Quando l'utente effettua una scelta, la determino e, in base a questa scelta, controllo il sistema operativo dell'utente. E dopo aver determinato quali elementi dell'interfaccia utente nascondere / aggiungere.
Ecco una sorta di pseudo-codice per quello che ho:
//OS enum
public enum OS {
WINDOWS, LINUX, MAC_OS_X;
}
//Servers enum
public enum SERVERS {
TOMCAT, IIS, NGINX;
}
//Server Listbox Handler
private void chooseServer() {
//...get value from list box
switch(server) {
case TOMCAT:
changeUI(getOS()); //getOS() returns OS enum value
break;
case IIS:
//IIS is for windows only
changeUI(OS.WINDOWS);
break;
case NGNIX:
//Temporary support only linux
changeUI(OS.LINUX);
break;
}
}
//UI changes here
private void changeUI(OS os) {
switch (os) {
case WINDOWS:
userNameField.setEnabled(true);
userPasswordField.setEnabled(true);
ipField.setVisible(false);
portField.setVisible(false);
serverPathField.setVisible(true);
break;
case LINUX:
userNameField.setEnabled(true);
userPasswordField.setEnabled(true);
ipField.setVisible(true);
portField.setVisible(true);
serverPathField.setVisible(false);
break;
case MAC_OS_X:
userNameField.setEnabled(false);
userPasswordField.setEnabled(false);
ipField.setVisible(false);
portField.setVisible(false);
serverPathField.setVisible(false);
break;
}
}
Non mi piace il momento in cui verranno aggiunti altri SO o nuovi server. Questi operatori di switch cresceranno di più e diventeranno più complicati, non parlo di manutenibilità di questo codice. Esistono approcci (modelli) standard per tali compiti che aiutano a evitare switch / if ... else grow e rendere il codice più generico, espandibile, leggibile e supportabile?
Ho provato ad implementare il pattern Adapter suggerito da Neil e ho funzionato in un momento oscuro. Ecco alcuni pseudo-codice:
public abstract class EditorAdapter {
protected boolean firstInit = true;
public abstract void adapt(Panel panel);
}
//--------
public class IISWindowsEditorAdapter extends EditorAdapter {
@Override
public void adapt(Panel panel) {
if(firstInit) {
firstInit = false;
panel.add(userNameField);
//add other elements
}
}
}
//--------
public class TomcatEditorAdapter extends EditorAdapter {
private OS os = getOS();
@Override
public void adapt(Panel panel) {
if(firstInit) {
firstInit = false;
if(OS == OS.LINUX) {
panel.add(userNameField);
//add other elements
} else if (OS == OS.WINDOWS) {
//add elements
} //... else if
}
}
}
//--------
public class Editor extends DialogEditor { //extends Dialog with protected Panel field (subPanel)
public Editor() {
initialize();
}
public void initialize() {
//...
main.add(createPanel()); //protected VerticalPanel main;
//...
}
public void createPanel() {
//listBox initialization
commonPanel.add(listBox); //panel with common elements
listBox.addClickHandler(new ChangeHandler() {
@Override
public void onChange(ChangeEvent event) {
selectServer();
});
}
//... add other common elements
}
private void selectServer() {
//... get selection
switch(server) {
//Here something should be done in order to control different layouts.
//At the moment, each choice adds more elements in addition to existing ones
//As a variant, one can create class fields for each adapter and manipulate with them using lazy initialization
case IIS:
new WindowsEditorAdapter().adapt(subpanel);
break;
case TOMCAT:
new TomcatEditorAdapter().adapt(subpanel);
break;
}
}
}
Il problema è che ho diverse tabelle / pannelli nel mio editor che alla fine vengono aggiunti al pannello principale. In generale, sembra:
-
apriamo una finestra di dialogo
-
scegli server web
-
alcuni elementi cambiano all'interno della finestra di dialogo in base alla nostra scelta (e alcune scelte sono influenzate dall'uso dell'OS dell'utente).
Ecco perché la prima inizializzazione dell'interfaccia utente con adattatore non funziona qui. Almeno non ho capito come implementare questo adattatore per la logica sopra.