AJS*_*S49 5 java oop state encapsulation agents
我最近一直在开发Java应用程序,并且我一直在尝试遵循GoF的状态模式来尝试整理代码.
该程序使用多代理系统的代理来代表"超级代理"评估指令(下面的示例).
超级代理可以以两种状态存在,并且如果语句到处检查状态然后执行特定于状态的行为,则会变得混乱.
这是该程序的(非常)简化版本.实际实现有更多的状态特定行为.
public class superAgent
{
//the state of the super agent
private States state;
//Contains information related to the operation of exampleClass. This should not be exposed through mutator methods.
private HashMap<String, SpecificInstructionData> instructionData
private LinkedBlockingQueue<ExampleInstruction> exampleQueue
private final Object instructionLock = new instructionLock
public enum States
{
STATE1,
STATE2;
}
public void setState(state s)
{
state = s
}
//Called by a thread that continuously takes from the queue
private void runningThread()
{
while(isRunning)
{
synchronized(instructionLock)
{
ExampleInstruction ei = exampleQueue.take();
//Add some data about the instruction into instructionData
//send the instruction to an available agent
}
}
}
public void instructionResponseRecievedFromAgent()
{
if(state == States.STATE1)
{
doState1Behavior();
}
else if(state == States.STATE2)
{
doState2Behavior();
}
}
private void doState1Behavior()
{
synchronized(instructionLock)
{
//make state specific modifications to instructionData
}
}
private void doState2Behavior()
{
synchronized(instructionLock)
{
//make state specific modifications to instructionData
}
}
}
Run Code Online (Sandbox Code Playgroud)
状态模式非常适合根据GoF模式将特定状态的行为封装到不同的类中(superAgent类将是上下文).然而,有两个问题,其中两个(IMO)打破封装:
大多数特定于州的行为需要对超级代理的私有成员(在上面的示例中,instructionData)进行更改.成员包含可能不应该访问的数据,绝对不应该是包装类的可变数据.
状态特定行为需要与非特定状态的行为同步.通过使其公开或使用getter而不暴露锁定对象(在上面的示例instructionLock中),状态和上下文无法共享锁定.公开锁会违反OOP,因为它可能会被包装/扩展类使用.
有没有人对我如何封装这种状态特定的行为有任何建议,请记住上面的例子和两点?
您可以通过在状态实例和实例之间使用Double DispatchsuperAgent来解决这两个问题,以避免破坏封装。
假设您已经实现了状态模式。instructionResponseRecievedFromAgent看起来像:
public void instructionResponseRecievedFromAgent() {
state.instructionResponseRecievedFromAgent();
}
Run Code Online (Sandbox Code Playgroud)
每个都以这种方式使用双重调度 State来实现:instructionResponseRecievedFromAgent
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();
}
}
Run Code Online (Sandbox Code Playgroud)
这样做你让每个人State指定要做什么,但由superAgent实例决定如何做。您可以完全访问状态和锁,而无需公开它们。
最后,您在 中实现instructionResponseRecievedFromAgentFromState1和:instructionResponseRecievedFromAgentFromState2superAgent
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
}
}
Run Code Online (Sandbox Code Playgroud)
请记住,虽然 eventinstructionResponseRecievedFromAgentFromState1和instructionResponseRecievedFromAgentFromState2是公共方法(因此State实例可以调用它们),但它们只能在状态模式的上下文中使用。