我最近一直在开发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
}
}
}
状态模式非常适合根据GoF模式将特定状态的行为封装到不同的类中(superAgent类将是上下文)。然而,有两个问题,其中两个(IMO)打破封装:
大多数特定于州的行为需要对超级代理的私有成员(在上面的示例中,instructionData)进行更改。成员包含可能无法访问的数据,肯定不应该是包装类的可变。
状态特定行为需要与非特定状态的行为同步。通过使其公开或使用getter而不暴露锁定对象(在上面的示例instructionLock中),状态和上下文无法共享锁定。公开锁会违反OOP,因为它可能会被包装/扩展类使用。
有没有人对如何封装这种状态特定行为有任何建议,请记住上面的例子和上述两点?
答案 0 :(得分:1)
您可以在状态实例和superAgent
实例之间使用Double Dispatch来解决这两个问题,以避免破坏封装。
假设您已经实现了状态模式。 instructionResponseRecievedFromAgent
看起来像是:
public void instructionResponseRecievedFromAgent() {
state.instructionResponseRecievedFromAgent();
}
每个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();
}
}
执行此操作,您可以让每个State
指定要执行的操作 ,但superAgent
实例会决定 如何执行此操作。您可以完全访问状态和锁定,而无需将其公开。
最后,您在instructionResponseRecievedFromAgentFromState1
中实施了instructionResponseRecievedFromAgentFromState2
和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
}
}
请注意,尽管instructionResponseRecievedFromAgentFromState1
和instructionResponseRecievedFromAgentFromState2
是公共方法(因此State
实例可以调用它们),但它们仅用于上下文国家格局。