GOF 状态模式状态转换实现问题

3
首先,当状态对象没有实例变量时,如何共享状态对象?这段文字摘自GOF的第308页,第3项(后果部分):
“如果状态对象没有实例变量 - 也就是说,它们所代表的状态完全编码在它们的类型中 - 那么上下文可以共享状态对象。当状态以这种方式共享时,它们本质上是轻量级的。”
有人能解释一下这段文字吗?
其次,状态转换决策有哪些方法?我的意思是决定传播哪个下一个状态?
请帮忙,谢谢。

你能解释一下你的第二个问题吗?通常状态系统不会决定要转换成哪个状态 - 这是由状态系统外部驱动的。它所做的只是定义状态和它们之间的转换。 - jon hanson
顺便提一下,这与C++关系不大。 - jon hanson
正如大家所知,状态模式并没有定义状态转换方法。因此,我想知道使用状态模式编写状态转换的方法是什么?请帮忙。谢谢。 - nicholas
这里描述的方法怎么样?https://dev59.com/hE7Sa4cB1Zd3GeqP21ow - nicholas
2个回答

2

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

例如,假设我想有三种状态“打开”、“激活”和“关闭”。我可能定义以下类:

abstract class State {};

class Open extends State {

  public Open() {}

}

class Active extends State {

  public Active() {}

}

class Closed extends State {

  public Closed() {}

}

--

另一个选项——我猜测这就是GOF文本中所暗示的与享元模式相结合的组合——是创建一个状态类,其中包含一堆静态成员(每个状态对应一个静态成员),然后可以共享使用。

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

alt text


谢谢您的解释。那共享状态对象怎么样? - nicholas
我想知道在什么情况下我们可以将享元模式和状态模式结合起来。 - nicholas

2
在状态模式中,使用状态对象来表示对象的状态。这些状态对象代表某个特定的状态,但它们本身没有任何可变状态。这意味着它们永远不会改变。因此,任意数量的对象可以同时使用相同的状态对象(甚至来自不同的线程)。如果状态对象具有可变状态,其他对象将不得不担心它们的状态对象被从其他地方改变。
将一个对象实例用于许多其他对象可以看作是享元模式的一个实例。
至于您问题的第二部分,这里有一个示例:
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;
};

所以,你基本上将对调用对象的引用传递给状态对象的每个方法。这样,状态对象就能在需要时改变调用者的状态。这个例子可能不是很美观,但我希望你能理解这个想法。

一个对象实例被许多其他对象使用可以被视为享元模式的一个实例。 - nicholas
那么你应该研究一下享元模式,因为这就是它的全部内容。 - Björn Pollex
我理解享元模式,但不知道它与状态模式有什么关系。 - nicholas
享元模式是关于在许多小对象之间共享一个大对象。大对象没有可变状态,因此不会发生冲突。 - Björn Pollex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接