Reputation: 1578
I want to implement FSM like below
ACTIVE_WAITING_STATE , ACTIVE_RUNNING_STATE , ACTIVE_END_STATE, so on PASSIVE_WAITING_STATE, PASSIVE_RUNNING_STATE, PASSIVE_END_STATE, so on
most functionalities are common for ACTIVE and PASSIVE states, just some small functions overrided. There is no problem until here. Problem is, All third level group have common functions. I mean, For example I have to implement 2 different increment() function one of is ACTIVE_xxx_STATEs, another one is PASSIVE_xxx_STATEs. How to do this without re-written for all states (eg. ACTIVE_WAITING_STATE , ACTIVE_RUNNING_STATE , ACTIVE_END_STATE, and also PASSIVE states)
To clearify my questions, my ugly sol'n. Problem is increment functions is same and re-written for all ActivexxxState (and also PassiveXXXState).
public class BaseState {
// Lots of functions
}
public class WaitingState extends BaseState{
// Lots of functions
}
public class RunningState extends BaseState{
// Lots of functions
}
public class EndState extends BaseState{
// Lots of functions
}
public Class ActiveWaitingState extends WaitingState {
// Few unique functions
private void increment() {
System.out.println("increment active");
}
}
public Class ActiveRunningState extends RunningState {
// Few unique functions
private void increment() {
System.out.println("increment active");
}
}
public Class ActiveEndState extends EndState {
// Few unique functions
private void increment() {
System.out.println("increment active");
}
}
public Class PassiveWaitingState extends WaitingState {
// Few unique functions
private void increment() {
System.out.println("increment passive");
}
}
public Class PassiveRunningState extends RunningState {
private void increment() {
System.out.println("increment passive");
}
}
public Class PassiveEndState extends EndState {
private void increment() {
System.out.println("increment passive");
}
}
Upvotes: 0
Views: 1392
Reputation: 533462
I would make increment() a protected method in BaseState so it is implemented once.
I have written an article on using enums to build a state machine. This can avoid the need to create classes everywhere for each state and still support some inheritance.
In answer to your comment.
abstract class BaseState {
public abstract boolean isPassive();
public boolean increment() {
System.out.println("increment "+(isPassize() ? "passive" : "active");
}
}
class PassiveState {
public boolean isPassive() { return true; }
}
If you don't want to have multiple isPassive methods you could assume a class naming convention
public boolean isPassive() { return getClass().getSimpleName().startsWith("Passive"); }
Upvotes: 2
Reputation: 90
If you share common behaviour in your state machine you have two possibilities to implement that.
1) You can add the common implementation to the base state, so it can be called by any state implementation that inherits from the base state. The visibility of these methods would be protected.
2) A better solution in my oppinion is that you move the common behaviour into its own class that is not related to the states class hierarchy at all.
So you can think about a strategy class that implements the common behaviour and is referenced by the base class and can be called by any state.
The second solution is better because it increases the testability of both, the state machine and the strategy class.
Upvotes: 0
Reputation: 39164
I'm not sure to have fully understand your question. Anyway, I'll suggest you to model active/passive state like a property in your class rather then use inheritance. Make your hierarchy something like:
public class BaseState {
boolean active; //active or passive
}
public class WaitingState extends BaseState {
}
...
Upvotes: 1