是否很好地使用状态模式来维护当前选定的对象?
Is it a good use of state pattern to maintain currently selected object?
状态模式的典型场景涉及状态大多不同的状态,如closed_connection_state
或open_connection_state
。就我而言,所有状态本质上都是相同的,但操作需要应用于当前选定的对象。
通常,这样的事情是使用指向当前选定对象的索引变量完成的,但是使用状态模式是否是更好的实现,就像下面的示例中一样?
class Object
{
std::string _name;
public:
Object(std::string name) : _name(name)
{
}
void Perform()
{
std::cout << _name << " Perform calledrn";
}
};
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
}
这绝对是一件合理的事情,如果你的状态成倍增加(就像状态机一样(,这可能会变得有点难以维护,但它实际上是一个很好的状态机的OO风格实现。
你可能希望你的状态(a&b(扩展一个共同的抽象状态,这样当功能在所有状态中都相同时,你不必在每个对象中实现它。
对于扩展,您可能还想"命名"您的状态并将它们放在哈希表中,一旦它扩展(请记住,在编程中您有 1 个或多个(,添加新状态不会对您的状态机进行代码更改 - 但我假设您已经有了这样的东西,并且只是缩小了这个问题。
另请注意,若要切换状态,您不想直接执行此操作(如示例所示(,您可能需要一个在 execute 方法返回时更改状态的方法 (setState(,而不是在 execute 方法本身或运行时更改状态。 事实上,你可以让 execute 返回一个字符串,指示它是下一个所需状态。
从评论编辑:
我所说的命名你的州的意思是,而不是:
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#会如何做到这一点(。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- 是否很好地使用状态模式来维护当前选定的对象?
- 类内非静态字段初始化 + 对象池 - >降低可维护性/可读性
- 维护C++对象,使用依赖于UI的方法
- C++维护子类对象的混合集合
- JNI/Android NDK-维护全局对象引用
- 如何将相互依赖的对象移动到一起并维护内部引用
- 在域驱动设计中,存储库模式是否维护对对象的引用
- 为什么我们需要维护自己的矩阵来转换游戏对象
- 如何使用容器中对象的继承层次结构来维护开放/封闭原则
- 函子如何维护/存储对象的状态
- 为渲染对象的所有实例维护一个指向共享纹理/资源的指针/引用的最佳方式
- 从默认构造函数调用重载构造函数时,维护对象状态信息
- 如何在C++中维护COM对象的弱引用
- 试着理解由字符串对象维护的指针