我的问题是:(上述|是什么)创建非侵入式前端的正确方法?

我用一个简化的例子来解释我的问题。

我有一个实现二叉树的后端:

// Back-end
struct Node
{
  Label label;
  Node* r, l;
};


我现在想实现前端以图形方式打印树。所以我的想法是通过包装后端来扩展图形属性:

// Front-end
struct Drawable
{
  uint x, y;
};

class Visitor;
template <class T> struct GNode : public Drawable
{
  T* wrapped;
  template <class V> void accept(V& v); // v.visit(*this);
}


现在存在创建访问者以打印二叉树的问题:

struct Visitor
{
    void visit(GNode<Node>& n)
    {
      // print the label and a circle around it: ok.

      if (n.wrapped.l) // l is a Node, not a GNode, I can't use the visitor on it
        // Problem: how to call this visitor on the node's left child?

      // the same with n.wrapped.r
    };
};


如评论中所述,后端不使用我的扩展类。

编写GNode“是”节点也不是解决方案,因为我必须将Node类中的accept()方法设置为虚拟方法并在GNode中覆盖它,但是我无法修改后端。然后,有人也可以说不需要在后端声明accept(),将Node *向下转换为GNode *即可。是的,它可以工作,但是很沮丧……

就我而言,我有约10种节点(它是一个图形),所以我正在寻找一种优雅,灵活的东西,并使用尽可能少的代码行(因此有包装模板的想法):)

非常感谢你。

最佳答案

完全分离代码是不可能的。他们必须说话。如果您确实要最大程度地实施去耦,则应使用某种IPC / RPC机制,并且该机制具有两个不同的程序。

话虽如此-我不喜欢访客模式。

您有一个图形对象,该对象与行为对象链接。行为和图形之间可能存在规则,例如边界不能重叠。

您可以在图形和行为之间建立实体关系,这是一个业务逻辑问题...

您将需要一些保存您的绘图上下文(img,屏幕,缓冲区)的thungus。

class DrawingThungus {
  void queue_for_render(Graphical*);
  void render();
};


图形用户将与行为具有继承关系或构图关系。
无论如何,他们将具有进行绘图所需的界面。

//abstract base class class Graphical  {
  get_x();
  get_y();
  get_icon();
  get_whatever();
};


如果您发现您的渲染器根据图形对象的类型而成为基于案例的对象,我建议将案例推至图形对​​象,并重构为get_primitives_list(),其中返回所需的基元以使图形对象返回(I假设您在某种程度上拥有核心图元,直线,圆,圆弧,标签等)。

我一直发现,OO分析很容易浪费精力,应该仅对即将完成的任务进行足够的分析。 YAGNI是一个伟大的原则。

10-07 15:21