patternjavaMinor
Set Game State from String
Viewed 0 times
gamestatefromstringset
Problem
Before I used reflection to invoke a state based on the string, it looked like this:
It is supposed to say
However, it feels wrong to use reflection when I know all the
They are:
I'm rendering the most straightforward solution to be along these lines:
Is it possible to clean that up?
For example, could instance-mapping be a solution?
There is a very similar situation with the
If the method can't be invoked in this class then it will be invoked in the state instead. Meaning, the exception can be caught for that reason.
However, i
public void setState (String state) {
try {
this.state = (State) Class.forName("state"+state).getConstructor().newInstance();
} catch (Exception e) {
System.out.println ("Tried to set state to " + state.toString() + ", but no such state exists.");
}
}It is supposed to say
...forName("state."+state). Notice the period in "state.".However, it feels wrong to use reflection when I know all the
State the project can be in.They are:
Title
NewGame
LoadGame
Credits
HighScore
World
I'm rendering the most straightforward solution to be along these lines:
private void setState (String state) {
switch (state) {
case "Title":
this.state = new Title ();
break;
case "NewGame":
this.state = new NewGame ();
break;
case "LoadGame":
this.state = new LoadGame ();
break;
case "Credits":
this.state = new Credits ();
break;
case "HighScore":
this.state = new HighScore ();
break;
case "World":
this.state = new World ();
break;
default:
System.out.println ("Tried to set state to " + state.toString() + ", but no such state exists.");
}
}Is it possible to clean that up?
For example, could instance-mapping be a solution?
There is a very similar situation with the
handle method. In the reflection case it looks like this:public void handle (Event event) {
try {
this.getClass().getMethod(event.getMethod(), String.class).invoke(this, event.getArgument());
} catch (Exception e) {
state.handle (event);
}
}If the method can't be invoked in this class then it will be invoked in the state instead. Meaning, the exception can be caught for that reason.
However, i
Solution
this.state = (State) Class.forName("state"+state).getConstructor().newInstance();This looks for a class named "stateWhatever", which isn't what you're doing below. Let's assume it's an error which happened when you copied the code.
private void setState (String state) {
switch (state) {
case "Title":
this.state = new Title ();
break;
case ....................
default:
System.out.println ("Tried to set state to " + state.toString() + ", but no such state exists.");
}
}Yes, this is going to get pretty long. But don't you simply separate the setting of the state from its computation?
private State getState() {
switch (state) {
case "Title":
return new Title ();
case ....Here, you save one line, you could save another one if your conventions allow it and that's the optimum.
In case you can precreate your states, then simply
private static final Map stateMap;
static {
Map map = new Map<>();
map.put("Title", new Title()):
...
stateMap = Collections.unmodifieableMap(map);
}would do. The usage is obvious.
In case you can't precreate your states, then you could create a
private static final Map> stateClassMap;and use reflection for the instance creation.
You're having many implementation of state and each of them has a no-args constructor. This looks like an
enum.System.out.println ("Tried to set state to " + state.toString() + ", but no such state exists.");You know that's no proper error handling, right?
Code Snippets
this.state = (State) Class.forName("state"+state).getConstructor().newInstance();private void setState (String state) {
switch (state) {
case "Title":
this.state = new Title ();
break;
case ....................
default:
System.out.println ("Tried to set state to " + state.toString() + ", but no such state exists.");
}
}private State getState() {
switch (state) {
case "Title":
return new Title ();
case ....private static final Map<String, State> stateMap;
static {
Map<String, State> map = new Map<>();
map.put("Title", new Title()):
...
stateMap = Collections.unmodifieableMap(map);
}private static final Map<String, Class<? extends State>> stateClassMap;Context
StackExchange Code Review Q#95159, answer score: 5
Revisions (0)
No revisions yet.