【问题标题】:Composite Pattern Reuse For Different Types不同类型的复合模式重用
【发布时间】:2012-04-11 19:10:09
【问题描述】:

扩展一个海军模拟项目,我希望添加复合模式,以便我可以拥有对象组。这是当前层次结构的样子:

class Sim_object {
};

class Ship : public Sim_object {
};

class Island : public Sim_object {
};

到目前为止,我想出了:

class Sim_object {
  // holds general sim functions
  get_name()
};

// COMPONENT
class Ship_object : public Sim_object {
  // holds ship functions
  add()
  remove()
  attack()
  move()
};

// COMPOSITE
class Group : public Ship_object {
   // holds list of group ship functions
   add()
   remove()
   attack()
   move()
};

// LEAF
class Ship : public Ship_object {
   // holds ship functions
   attack()
   move()
};

class Island : public Sim_object {
  // holds island functions
};  

我有它的工作,但它只适用于船舶和船舶组。我想重用组代码(添加、删除、显示等),这样一个具体的组类(如 Island_group)就可以从中继承并使用它。我尝试更改 Ship_group 类从名为 Group 的公共基类继承的设计,但我遇到了一个菱形程序。

我有什么办法可以根据类型重用我的组控制代码吗?

【问题讨论】:

  • 这在我看来不像是复合的

标签: c++ inheritance design-patterns composite


【解决方案1】:

为了与不止一种类型的Sim_object 一起工作,组合应该继承和组合Sim_objects

class Sim_object { };
class Ship : public Sim_object { };
class Island : public Sim_object { }; 
class Group : public Sim_object { 
  add()
  remove()
}; 

要将其定制为特定类型,您可以对其进行模板化,并(可能)从中派生其他组:

template <class T>
class Group : public Sim_object {
  add()
  remove()
};

class Ship_Group : public Group<Ship> {
  attack()
  move()
};

class Island_Group : public Group<Island> { } // possibly unnecessary

现在,要让您的Ship_Group 替代Ships,您可以为Ship 创建一个“接口”(纯虚拟类)并从它继承Ship_Group。您还可以在客户端代码中使用新界面而不是具体的 Ship

class Ship_Like { // interface
  attack() = 0
  move() = 0
};
class Ship : public Sim_object, public Ship_Like { }; // concrete
class Ship_Group : public Group<Ship>, public Ship_Like { 
  attack()
  move()
}

不用担心那里的钻石问题...

【讨论】:

  • Group 类中的容器持有什么类型的对象?我知道它是模板化的,但是当 Ship_group 使用 Group 从它派生时,我会收到错误,因为我的容器正在尝试保存抽象类的对象。
  • 嗯,应该可以的。不管怎样,我把它改成了Group&lt;Ship&gt;。如果您想要递归组合(组的组......),请使用Group&lt;Ship_Like&gt;。你得到了什么错误?用什么代码?
  • 我遇到的问题是哪些类负责哪些职责。在复合模式中,客户端应该与一个类交互来处理船舶和船舶组。我得到了 Ship_like 的工作;但是现在我不确定在哪里处理 Add()/Remove()。我希望能够检索 Ship_like 对象,然后通过它添加或删除它。我需要向 Ship_like 添加添加/删除功能吗?我猜在添加/删除船舶时,客户端与代码的哪一部分交互。同样,我需要能够访问父、名称和位置函数的 Sim_object 函数
  • 此外,我还有 get_object() 函数,因此我可以根据名称检索所述对象。我在 Group 中的容器是 shared_ptrs 的映射。
  • add/remove 应该是组合的一部分 (Group)。添加或删除组件的代码必须知道它正在处理Group
猜你喜欢
  • 2015-08-04
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 2015-02-26
  • 2019-06-03
  • 2021-10-07
  • 2021-01-28
  • 1970-01-01
相关资源
最近更新 更多