6

我最近一直在开发 Java 应用程序,并且一直在尝试遵循 GoF 的状态模式来尝试整理代码。

该程序使用多代理系统的代理来代表“超级代理”评估指令(示例如下)。

超级代理可以以两种状态存在,并且到处都有 if 语句检查状态然后执行特定于状态的行为会变得很混乱。

这是该程序的(非常)简化版本。实际实现具有更多特定于状态的行为。

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)都破坏了封装:

  1. 大多数特定于状态的行为都需要对超级代理的私有成员(在上面的示例中为指令数据)进行更改。成员包含的数据可能不应该被访问,并且绝对不应该对包装类是可变的。

  2. 特定于状态的行为需要与非特定于状态的行为同步。如果不通过公开或使用 getter 来公开锁对象(在上面的示例指令锁中),则状态和上下文无法共享锁。公开锁违反了 OOP,因为它可能被包装/扩展类使用。

考虑到示例和上述两点,是否有人对我如何封装这种特定于状态的行为有任何建议?

4

1 回答 1

2

您可以通过在状态实例和实例之间使用Double DispatchsuperAgent来解决这两个问题,以避免破坏封装。

假设您已经实现了状态模式。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做的是实例。您可以完全访问状态和锁定,而无需将它们公开。

最后,您同时实现instructionResponseRecievedFromAgentFromState1and instructionResponseRecievedFromAgentFromState2in 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
    }
}

请记住,尽管 eventinstructionResponseRecievedFromAgentFromState1instructionResponseRecievedFromAgentFromState2是公共方法(因此State实例可以调用它们),但它们仅用于状态模式的上下文中。

于 2013-11-04T17:46:24.210 回答