3

首先,谁能解释当状态对象没有实例变量时如何共享状态对象?

本文摘自 GOF,第 308 页,第 3 项(后果部分):

状态对象可以共享。如果状态对象没有实例变量——也就是说,它们所代表的状态完全以其类型编码——那么上下文可以共享一个状态对象。当以这种方式共享状态时,它们本质上是轻量级的。

谁能解释这段文字?

其次,状态转换决策的方法是什么?我的意思是决定传播哪个下一个状态?

请帮忙。谢谢。

4

2 回答 2

2

该段落基本上是说您将状态编码为单独的类 - 然后实例类型是“状态”并且类不需要任何实例变量,因为它们的类型编码了您需要的所有信息。

例如说我想要三个状态“打开”、“活动”和“关闭”。我可能会定义以下类:

abstract class State {};

class Open extends State {

  public Open() {}

}

class Active extends State {

  public Active() {}

}

class Closed extends State {

  public Closed() {}

}

--

另一种选择-我怀疑这是与GOF文本中暗示的flyweight的组合,将创建一个状态类,其中可以共享一堆静态成员(每个状态一个)-

public class State {

  private string name;

  private State(String name) {
    this.name = name;
  }

  public final static State OPEN = new State("Open");
  public final static State ACTIVE = new State("Active");
  public final static State CLOSED = new State("Closed");

}

我不得不去挖掘以提醒自己所有这些东西是如何详细工作的。Kerievsky 对此进行了很好的描述(我从上面的一个示例中大量借鉴了!)以及如何通过从状态类中进行子类化来处理状态转换,以创建管理每个转换的类。请参阅“重构为模式”(ISBN:0321213351)

编辑(2):他的网站有一个他的例子的类图 - http://www.industriallogic.com/xp/refactoring/alteringConditionalsWithState.html

替代文字

于 2010-07-02T10:32:54.633 回答
2

在状态模式中,您可以使用状态对象来表示对象的状态。这些状态对象代表某种状态,但它们自己没有任何可变状态。这意味着他们永远不会改变。因此,任意数量的对象可以同时使用同一个状态对象(即使来自不同的线程)。如果状态对象具有可变状态,则其他对象将不得不担心它们的状态对象从其他地方被更改。

许多其他对象对一个对象实例的使用可以看作是flyweight-pattern的一个实例。

至于你问题的第二部分,这里有一个例子:

class SomeStateMachine;

class AbstractState {
    // abstract baseclass for all state-classes
    void input(const std::string & data, SomeStateMachine & caller) = 0;
}

class FinalState : public AbstractState {
    FinalState * getInstance(); // always returns same instance
}

class InitialState : public AbstractState {
public:
    InitialState * getInstance(); // always returns same instance
    void input(const std::string & data, SomeStateMachine & caller) {
        std::cout << data << std::endl;
        caller.m_State = FinalState::getInstance();
    }
}

class SomeStateMachine {
public:
    SomeStateMachine() : m_State(InitialState::getInstance())
    void input(const std::string & data) {
        m_State->input(data, *this);
    }
private:
    friend class InitialState;
    AbstractState * m_State;
};

因此,您基本上将对调用对象的引用传递给您的状态对象的每个方法。这样,状态对象能够在需要时更改调用者的状态。这个例子可能不是很漂亮,但我希望你能明白。

于 2010-07-06T07:54:42.710 回答