我正在为状态机表示编写图编辑器应用程序。我有两个在画布和图表上运行的交互工具。第一个称为“编辑工具”,负责创建新的图元素,例如节点和边。第二个被称为“移动工具”并作用于图表布局,id est,它移动节点并更新边缘。这是简化的解释,但我不需要提供更多细节来提问我。
我想知道处理事件并在各种工具中分发事件的最有效和最有条理的方法是什么
我知道我可以简单地拦截他们调用的事件并根据所选工具,当前状态和目标对象进行一些处理,但这样代码扩展到巨大的if (...) else if (...)
块,上下文标志等;并且变得非常难以维护。
这种情况是否有任何常见的代码模式?你能举一些例子吗?我可以看一下哪些开源项目可以了解更多信息?
答案 0 :(得分:1)
我不确定我的问题是否正确。从阅读问题看来,您正在寻找观察者设计模式。但是,你对自己的问题给出的答案并不符合这种解释......
如果你想要,例如每次更改状态机时您的UI都会更新,那么您可能希望查看Wikipedia,CodeProject处的观察者模式或只是谷歌搜索它。这是最常见的设计模式之一,如果你不了解它,你肯定应该花几分钟时间来熟悉它。
作为关于如何将此模式应用于您的域的示例,假设您希望每当用户使用编辑工具添加或删除节点/边时,LayoutManager都会重绘图。您不希望直接从编辑工具中调用LayoutManager,因为这将强烈couple这两个组件。因此,您可以按如下方式指定一个观察者界面(我在这里使用C ++,因为我不知道您的应用程序是用哪种语言编写的):
class StateMachineModelObserver
{
public:
virtual void nodeChanged(Node* n)=0;
virtual void edgeChanged(Edge* e)=0;
};
让任何想要通知状态机模型更改的主题从该类继承并实现其功能。 E.g:
class MyStateMachineLayoutManager : public StateMachineModelObserver
{
public:
void foo() {} // these are
void bar() {} other functions of the layout manager
virtual void nodeChanged(Node* n)
{
redraw();
}
virtual void edgeChanged(Edge* e)
{
redraw();
}
};
现在您需要您的状态机模型提供允许订阅和取消订阅通知的功能,您需要发送通知。
class MyStateMachineModel
{
public:
Node* addNode()
{
Node* n=new Node();
insertNodeIntoModel();
notify(n);
return n;
}
void subscribe(StateMachineModelObserver* o)
{
m_mutex.lock();
m_observers.insert(o);
m_mutex.unlock();
}
void unsubscribe(StateMachineModelObserver* o)
{
m_mutex.lock();
m_observers.insert(o);
m_mutex.unlock();
}
private:
void notify(Node* n)
{
m_mutex.lock();
for_each(m_observers.begin(), m_observers.end(),
[](StateMachineModelObserver* o)
{
o->nodeChanged(n);
}
);
m_mutex.unlock();
}
std::set<StateMachineModelObserver*> m_observers;
std::mutex m_mutex;
};
现在,您所要做的就是将LayoutManager订阅到状态机模型,每次模型更改时(此处:正在添加节点),它都会自动得到通知。您可以为不同的通知设置不同的观察者界面,或者您可以使用单个观察者界面,为不同类型的通知提供单独的功能。
答案 1 :(得分:0)
我刚刚发现了一篇非常好的文章,描述了可以使用状态机操作的GUI设计:http://lassala.net/2008/02/05/state-machines-and-gui-interaction-part-i/