设计替代?组成和结构

时间:2010-01-05 03:39:41

标签: c++ design-patterns

所以我正在使用组合将一组对象组合在一起,所有对象都是从基类派生出来的,比如说Component。 E.g:

class Component {
public:
  Component();
  ...
private:
  int m_address;
  ...
};

class SpecializedComponent: public Component {
public:
  SpecializedComponent()
  ... //and so on
};

class SpecializedComponent2: public Component {
public:
  SpecialIzedComponent2()
  ... //and so on
};

class ComponentHolder{
  SpecializedComponent* m_descriptiveName;
  SpecializedComponent2* m_descriptiveName2;
  // and so on... many different types of components
}

因此,每个SpecializedComponentX将通过网络与单个数据源进行通信,每个数据源都有自己唯一的地址。这些地址在参数文件中指定。目前,我正在解析参数文件,并在派生类构造函数中初始化m_address - 这是因为每个m_address都是由我们正在初始化的对象类型指定的。

每个SpecializedComponentX都有一些我想在基类Component中执行的常用功能。所以,我启动了一个与基类Component相关的线程,对吧?当然 - 有道理。直到我意识到我还没有该组件的目标地址 - 因为该对象尚未完全构建。我想在ctor中启动基类线程,但我还不知道m_address

我能想到解决这个问题的唯一方法是提供一个(简单的)虚函数void start(),一旦对象完全构造,派生类就可以调用它来旋转线程。这是有效的适当的设计选择还是有一种我可以忽略的模式?谢谢。

3 个答案:

答案 0 :(得分:0)

Component可以有一个构造函数,其中一个参数初始化m_address。

答案 1 :(得分:0)

如果这个常见功能以任何方式取决于SpecializedComponent,SpecializedComponent2的状态,或者这是一个SpecializedComponent或SpecializedComponent2,那么除非你传入参数,否则你不能在Component的构造函数中真正做到这一点。它。将类型标识符传递给Component构造函数来进行此类初始化有时是一种必要的恶魔。

但是,在这种情况下,您可以创建派生类可以调用的虚函数。但是,假设您将此虚函数调用放在SpecializedComponent构造函数中。如果你以后从这个(SuperSpecializedComponent)派生了另一个类并且对这个虚函数进行了ovrerride,你从SpecialzedComponent构造函数调用的调用甚至都不会。道德:不要从构造函数中调用虚函数。

我认为最干净的方法是采用两相结构。一个构造函数,用于对象的基本连接以及必须在使用之前调用的Init()方法。在完全构造所有对象之后,客户端代码(ComponentHolder?)可以调用此Init。

答案 2 :(得分:0)

为什么start()方法需要是虚拟的?

您可以将其设置为非虚拟并实现派生的构造函数 像这样:

SpecializedComponent::SpecializedComponent() {
    m_address = getAddressFromParameterFile("SpecializedComponent");
    start();
}

这比在对象完全后调用start()更好 因为两步构造容易出错。 (如果你这样做 需要两步施工,考虑工厂(或工厂方法) 确保只存在完全构造的对象。制作构造函数 私人和工厂(方法)的朋友。)

另一种方法是将地址的计算移出 对象构造。这将产生如下代码:

SpecializedComponent::SpecializedComponent(const std::string& address)
 : Component(address)
{}

Component::Component(const std::string& address)
 : m_address(address)
{
    start();
}

这种方法提高了派生的可测试性 SpecializedComponents,因为它消除了对它的依赖 参数文件。

为方便起见,您可以为实例提供静态工厂方法 您的SpecializedComponents:

SpecializedComponent* SpecializedComponent::create() {
    std::string address = getAddressFromParameterFile("SpecializedComponent");
    return new SpecializedComponent(address);
}

BTW:考虑在ComponentHolder中保存shared_ptr,而不是原始指针。