是否可以很好地利用状态模式来维护当前选定的对象?

问题描述 投票:0回答:1

状态模式的典型情况涉及大多数不同的状态,如closed_connection_stateopen_connection_state。在我的例子中,所有状态基本相同,但操作需要应用于当前选定的对象。

通常这样的事情是使用指向当前所选对象的索引变量完成的,但使用状态模式是一个更好的实现来执行此操作,如下例所示?

class Object
{
    std::string _name;
public:
    Object(std::string name) : _name(name)
    {

    }

    void Perform()
    {
        std::cout << _name << " Perform called\r\n";
    }
};

class CurrentObject
{
    Object* _a;
    Object* _b;
    Object* _current;

public:

    CurrentObject(Object* a, Object* b) : _a(a), _b(b)
    {
        _current = a;
    }

    void Perform()
    {
        _current->Perform();

        // Update _current logic goes here, lets just switch
        // the state whenever `Perform` is called.
        if (_current == _a)
            _current = _b;
        else
            _current = _a;
    };

};

int main()
{
    Object a("a"); // program can be in a state when `a` is the current object.
    Object b("b"); // or b can become the current object as result of an operation on current object

    CurrentObject current(&a, &b); // it assigns the defaults

    // assume Perform() does its thing but it also needs to change the current selected object.
    // In this example, we assumes the current selection object is always swapped.
    current.Perform(); // operates on `a`, the default
    current.Perform(); // operates on `b` due state changed in above line
    current.Perform(); // operates on `a` doe to state changed in above line again
}
c++ oop design-patterns state
1个回答
2
投票

这绝对是一个合理的事情,如果你的状态成倍增加(因为状态机倾向于),这可能会变得有点难以维护,但它实际上是状态机的非常好的OO样式实现。

您可能希望状态(a和b)扩展一个公共抽象状态,以便当所有状态的功能相同时,您不必在每个对象中实现它。

对于扩展,您可能还希望“命名”您的状态并将它们放入哈希表中,一旦它扩展(请记住,在编程中您有1个或多个)添加新状态不会将代码更改到您的状态机 - 但我认为你已经有了这样的东西,只是为了解决这个问题。

另请注意,要切换状态,您不希望直接执行它(作为示例),您可能需要一个方法(setState),它在perform方法返回时更改状态,而不是在perform方法本身或运行时。实际上,您可以执行返回一个字符串,指示它是下一个所需的状态。

从评论中编辑:

我的意思是命名你的状态而不是:

class CurrentObject
{
    Object* _a;
    Object* _b;
    Object* _current;
    ...

你可能有类似的东西(请原谅我的java语法,C#不是我的主要语言,但我知道它在功能上非常相似)

class CurrentObject
{
    Hashtable states=new Hashtable();
    Object* _current;

    public addState(String stateName, Object* state)
    {
        states.put(stateName, state)
    }

    public void Perform()
    {
        String nextState = _current->Perform();
        if(nextState != null)
            setState(nextState);
    }
    public void setState(String stateName)
    {
        _current = states.get(stateName);
    }

}

您的调用代码将执行以下操作:

currentObject = new CurrentObject()
currentObject.addState("state a", _a);
currentObject.addState("state b", _b); 
currentObject.setState("state a");
currentObject.perform();
...

我忽略了很多初始化和错误检查。

您的状态机目前只有一个事件:“Perform()”。您可能会发现需要其他事件会使事情变得复杂一些(在java中我可能会使用反射或注释来解决这个问题,不确定C#会怎么做)。

© www.soinside.com 2019 - 2024. All rights reserved.