You can solve both problems by using Double Dispatch between the state instances and the superAgent
instance to avoid breaking encapsulation.
Say you already implemented the State Pattern. instructionResponseRecievedFromAgent
would look like:
public void instructionResponseRecievedFromAgent() {
state.instructionResponseRecievedFromAgent();
}
Each State
implements instructionResponseRecievedFromAgent
using double dispatch this way:
abstract class State {
abstract void instructionResponseRecievedFromAgent();
}
class State1 extends State {
void instructionResponseRecievedFromAgent() {
// instance variable
agent.instructionResponseRecievedFromAgentFromState1();
}
}
class State1 extends State {
void instructionResponseRecievedFromAgent() {
// instance variable
agent.instructionResponseRecievedFromAgentFromState2();
}
}
Doing this you let the each State
specify what to do, but is the superAgent
instance who decides how to do it. You have full access to the state and locks without making them public.
Finally, you implement both instructionResponseRecievedFromAgentFromState1
and instructionResponseRecievedFromAgentFromState2
in superAgent
:
public void instructionResponseRecievedFromAgentFromState1() {
//this is doState1Behavior original implementation
synchronized(instructionLock)
{
//make state specific modifications to instructionData
}
}
public void instructionResponseRecievedFromAgentFromState2() {
//this is doState1Behavior original implementation
synchronized(instructionLock)
{
//make state specific modifications to instructionData
}
}
Keep in mind that, event though instructionResponseRecievedFromAgentFromState1
and instructionResponseRecievedFromAgentFromState2
are public methods (so the State
instances can call them), they're only meant to be used only in the context of the State Pattern.