我使用下面的例子来实现状态设计模式。
https://sourcemaking.com/design_patterns/state/cpp/1
我不想删除成员类中的* this指针因为不安全(我会在删除后调用其他成员函数)。
class ON: public State
{
public:
ON()
{
cout << " ON-ctor ";
};
~ON()
{
cout << " dtor-ON\n";
};
void off(Machine *m);
};
class OFF: public State
{
public:
OFF()
{
cout << " OFF-ctor ";
};
~OFF()
{
cout << " dtor-OFF\n";
};
void on(Machine *m)
{
cout << " going from OFF to ON";
m->setCurrent(new ON());
delete this; // <<< This line looks suspect and unsafe
}
};
void ON::off(Machine *m)
{
cout << " going from ON to OFF";
m->setCurrent(new OFF());
delete this; // <<< This line looks suspect and unsafe
}
有没有更好的方法来实现状态设计模式?我想过使用单身人士,但我想避免使用单身人士。
致以最诚挚的问候,
答案 0 :(得分:2)
&#34; ...但我想避免使用单身人士。&#34;
这可能是他们罕见的有效用例之一,因为状态应该是无状态本身(这并不代表他们不需要实例),以及无论当前状态机的上下文如何,都可以同时访问 这意味着你实际上一次只需要一个状态的实例。
上述网站上显示的示例也会给您带来不必要的性能影响,只要状态发生变化,new
和delete
就会产生不必要的性能损失,这可以避免稳定{{1}州的实例。
实际上,您可以考虑像Flyweight Design Pattern一样提供状态实例,这实际上归结为 Singleton 状态实例。
但是,这取决于。 UML状态图实际上允许具有非无状态状态(具有历史属性或活动状态的复合状态)。
查看我的STTCL template library concept document,它解释了我用过的一些方面和设计决策,开发模板库以及如何正确使用它。
请放心,我在那里没有任何单static
; - )。
我说网站目前提供的示例,设计非常糟糕,一般不推荐 1 。
正如您所提到的,使用delete this;
并不合适,危险且不可接受。
使用 Singleton 时,如果您手边有有效的用例。
1) 可悲地注意到这一点,因为我已经将它作为&#34;参考&#34; 用于许多{ {3}}此处有相关问题。
答案 1 :(得分:2)
您的链接中使用的设计是:
正如here所述,如果采取额外的谨慎措施,这可能会有效。您的代码尊重先决条件。
另一种方法是状态机删除setCurrent()
中的当前状态。但更糟糕的是:一旦机器删除了对象,该对象就不再存在,因此当setCurrent()
返回时,您事实上处于与以前相同(危险)的情况下(使用{ {1}}),重要的区别在于这并不明显。
修改强>
如果您对此构造感到不自在,可以选择变体:
delete this
在这种情况下,需要稍微更新状态机功能:
class Machine
{
class State *current; // current state
class State *nextstate; // null, unless a state transition was requested
void check_transition(); // organise switch to nextstate if transition is needed
public:
Machine();
void setCurrent(State *s)
{
nextstate = s; // only sets the info about nextstate
}
void set_on();
void set_off();
};
然后状态机将管理状态转换:
void Machine::set_on()
{
current->set_on(this); // as before
check_transition(); // organise the transition if the transition was requested
}
机器组织删除未使用的状态。请注意,此方法允许使用shared_ptr而不是原始指针。
这里有一个小online proof of concept。
顺便说一下:机器析构函数还应该删除当前和下一个状态,以免泄漏。无论如何,状态析构函数应该被定义为虚拟