我有这两个类似的课程。你会用什么设计来分解代码?

时间:2014-12-04 03:31:16

标签: c++ templates inheritance code-duplication

我有一个非常复杂的图形数据结构。为了清楚起见,我们将其简化为:

class Node;
class AbstractEdge { void foo() {} };
class Edge1: public AbstractEdge { void bar1() {} };
class Edge2: public AbstractEdge { void bar2() {} };

正如您所看到的,我们的图形与任何其他图形不同:存在两种边缘,两者都继承自AbstractEdge。这种设计无法改变。现在,假设我必须设计两个类:

class OrientedEdge1
{
  Edge1 * edge;
  bool orientation;

  void foo() { edge->foo(); } 
  void bar1() { edge->bar1(); }
}

class OrientedEdge2
{
  Edge2 * edge;
  bool orientation;

  void foo() { edge->foo(); }
  void bar2() { edge->bar2(); }
}

实际上,OrientedEdge1 :: foo()和OrientedEdge2 :: foo()比调用单个方法要长得多,但想法是它们是相同的,只调用从AbstractEdge继承的方法。

您将使用什么样的设计来分解代码?我正在考虑三种方法:

1。使用免费功能

foo_impl(AbstractEdge * edge) { edge->foo(); }

class OrientedEdge1
{
  Edge1 * edge;
  bool orientation;

  void foo() { foo_impl(edge); }
  void bar1() { edge->bar1(); }
}

class OrientedEdge2
{
  Edge2 * edge;
  bool orientation;

  void foo() { foo_impl(edge); }
  void bar2() { edge->bar2(); }
}

优点:

  • 非常简单的解决方案,比完全没有分解要好得多。

缺点:

  • 并非所有方法都可以作为自由函数实现。

  • 声明代码仍然重复。

2。使用继承

class AbstractOrientedEdge
{
  AbstractEdge * edge;
  bool orientation;

  void foo() { edge->foo(); }
}

class OrientedEdge1: public AbstractOrientedEdge
{
  Egde1 * edge1() { return static_cast<Egde1*>(edge); }

  void bar1() { edge1()->bar1(); }
}

class OrientedEdge2: public AbstractOrientedEdge
{
  Egde2 * edge2() { return static_cast<Egde2*>(edge); }

  void bar2() { edge2()->bar2(); }
}

优点:

  • 更多因素化。

  • 我不打算以多态方式使用这两个类,但谁知道,也许它们通过继承相关的事实可能在将来变得有用。

缺点:

  • 在构造函数/ setter中需要注意强制OrientedEdge1 :: edge始终指向Egde1 *。

  • 不知何故,static_cast感觉不对。

3。使用模板

template <class EdgeT>
class OrientedEdge
{
  EdgeT * edge;
  bool orientation;

  void foo() { edge->foo(); }
}

class OrientedEdge1: public OrientedEdge<Edge1>
{
  void bar1() { edge->bar1(); }
}

class OrientedEdge2: public OrientedEdge<Edge2>
{
  void bar2() { edge->bar2(); }
}

优点:

  • 大部分因素化。

  • 存储在两个类中的指针都具有正确的类型,不需要转换。

缺点:

  • 需要在标题中保持共享代码的实现,强制包含AbstractEdge.h(可以使用以前的方法使用前向声明来避免)。

问题:您倾向于使用哪种方法?你有其他解决方案或建议吗?

1 个答案:

答案 0 :(得分:1)

1和3。

3删除重复的样板,1移动实现,无论我想要什么。