1

我正在为状态机表示编写一个图表编辑器应用程序。我有两个在画布和图表上操作的交互工具。第一个称为“编辑工具”,负责创建新的图表元素,例如节点和边。第二个称为“移动工具”,作用于图表布局,id est,它移动节点并更新边缘。这是简化的解释,但我不需要给你更多细节来问我的问题。

我想知道处理事件并将它们分布在工具中的最有效和最有组织的方式是什么

我知道我可以简单地拦截他们调用的事件并根据所选工具、当前状态和目标对象进行一些处理,但是这样代码会扩展到一个巨大的if (...) else if (...)块、上下文标志等;并且变得非常难以维护。

这种情况有没有常见的代码模式?你能举一些例子吗?我可以查看哪些开源项目以了解更多信息?

4

2 回答 2

1

我不完全确定你的问题是否正确。通过阅读问题,您似乎正在寻找观察者设计模式。但是,您对自己问题的回答并不真正符合这种解释......

如果您希望在每次更改状态机时更新您的 UI,那么您可能希望查看WikipediaCodeProject上的观察者模式,或者只是 google 一下。它是最常见的设计模式之一,如果您不了解它,您绝对应该花几分钟来熟悉它。

作为如何将此模式应用于您的域的示例,假设您希望您的 LayoutManager 在用户使用编辑工具添加或删除节点/边时重新绘制图表。您不想直接从编辑工具中调用 LayoutManager,因为这会强烈地耦合这两个组件。因此,您可以按如下方式指定观察者接口(我在这里使用 C++,因为我不知道您的应用程序是用什么语言编写的):

class StateMachineModelObserver
{
public:
   virtual void nodeChanged(Node* n)=0;
   virtual void edgeChanged(Edge* e)=0;
};

让任何想要通知状态机模型更改的主体从该类继承并实现其功能。例如:

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 订阅到状态机模型,并且每次模型更改(这里:正在添加一个节点)时,它都会自动收到通知。您可以为不同的通知设置不同的观察者接口,也可以为不同类型的通知设置一个具有不同功能的观察者接口。

于 2012-09-30T17:22:31.627 回答
0

我刚刚发现了一篇很好的文章,描述了可以使用状态机操作的 GUI 设计:http: //lassala.net/2008/02/05/state-machines-and-gui-interaction-part-i /

于 2012-09-29T21:37:19.843 回答