Modifica Come sottolineato da Steve Evers e pdr, non sto implementando correttamente il pattern di Memento, il mio design è in realtà State pattern.
Menu Programma
Ho creato un programma di menu basato su console con più livelli che seleziona un determinato test da eseguire. Ogni livello descrive più precisamente l'operazione. A qualsiasi livello puoi digitare indietro per tornare indietro di un livello ( memento ).
Level 1: Server Type?
[1] Server A [2] Server B
Level 2: Server environment?
[1] test [2] production
Level 3: Test type?
[1] load [2] unit
Level 4: Data Collection?
[1] Legal docs [2] Corporate docs
Level 4.5 (optional): Load Test Type
[2] Multi TIF [2] Single PDF
Level 5: Command Type?
[1] Move [2] Copy [3] Remove [4] Custom
Level 6: Enter a keyword
[setup, cleanup, run]
design
States
PROBLEMA:
In questo momento l'enume degli STATI è il fattore determinante su quale stato è INDIETRO e quale stato è NEXT eppure non sa nulla su quale sia lo stato del ricordo corrente.
Qualcuno ha riscontrato un problema simile e ha trovato un modo efficace per gestire i ricordi con lo stato opzionale?
static enum STATES {
SERVER, ENVIRONMENT, TEST_TYPE, COLLECTION, COMMAND_TYPE, KEYWORD, FINISHED
}
Soluzione possibile (non flessibile)
In riferimento al mio codice qui sotto, ogni istruzione case nella classe Menu può controllare lo stato di currentMemo e quindi impostare lo STATE (enum) di conseguenza per passare al Builder. Tuttavia, questo non sembra flessibile e molto flessibile da cambiare e non riesco a vedere un modo efficace di ridefinire il design.
class Menu extends StateConscious {
private State state;
private Scanner reader;
private ServerUtils utility;
Menu() {
state = new State();
reader = new Scanner(System.in);
utility = new ServerUtils();
}
// Recurring menu logic
public void startPromptingLoop() {
List<State> states = new ArrayList<>();
states.add(new State());
boolean redoInput = false;
boolean userIsDone = false;
while (true) {
// get Memento from last loop
Memento currentMemento = states.get(states.size() - 1)
.saveMemento();
if (currentMemento == null)
currentMemento = new Memento.Builder(0).build();
if (!redoInput)
System.out.println(currentMemento.prompt);
redoInput = false;
// prepare Memento for next loop
Memento nextMemento = null;
STATES state = STATES.values()[states.size() - 1];
// get user input
String selection = reader.nextLine();
switch (selection) {
case "exit":
reader.close();
return; // only escape
case "quit":
nextMemento = new Memento.Builder(first(), currentMemento,
selection).build();
states.clear();
break;
case "back":
nextMemento = new Memento.Builder(previous(state),
currentMemento, selection).build();
if (states.size() <= 1) {
states.remove(0);
} else {
states.remove(states.size() - 1);
states.remove(states.size() - 1);
}
break;
case "1":
nextMemento = new Memento.Builder(next(state), currentMemento,
selection).build();
break;
case "2":
nextMemento = new Memento.Builder(next(state), currentMemento,
selection).build();
break;
case "3":
nextMemento = new Memento.Builder(next(state), currentMemento,
selection).build();
break;
case "4":
nextMemento = new Memento.Builder(next(state), currentMemento,
selection).build();
break;
default:
if (state.equals(STATES.CATEGORY)) {
String command = selection;
System.out.println("Executing " + command + " command on: "
+ currentMemento.type + " "
+ currentMemento.environment);
utility.executeCommand(currentMemento.nickname, command);
userIsDone = true;
states.clear();
nextMemento = new Memento.Builder(first(), currentMemento,
selection).build();
} else if (state.equals(STATES.KEYWORD)) {
nextMemento = new Memento.Builder(next(state),
currentMemento, selection).build();
states.clear();
nextMemento = new Memento.Builder(first(), currentMemento,
selection).build();
} else {
redoInput = true;
System.out.println("give it another try");
continue;
}
break;
}
if (userIsDone) {
// start the recurring menu over from the beginning
for (int i = 0; i < states.size(); i++) {
if (i != 0) {
states.remove(i); // remove all except first
}
}
reader = new Scanner(System.in);
this.state = new State();
userIsDone = false;
}
if (!redoInput) {
this.state.restoreMemento(nextMemento);
states.add(this.state);
}
}
}
}