在C ++中处理多个对象依赖的最佳方法是什么?

时间:2009-02-20 23:29:45

标签: c++

我正在构建一个C ++应用程序,并且我有几个实用程序对象,我的所有类都需要使用它们。这些是日志对象,全局状态对象,DAL对象等......

到目前为止,我一直将所有这些对象作为引用传递给我的类构造函数。

例如:

class Honda : public Car
{
    public:
        Honda ( const GlobalState & state, 
                const Log & logger, 
                const DAL & dal );

    ...

    private:
      const GlobalState & my_state;
      const Log & my_logger;
      const DAL & my_dal;
}

这很快就会变得乏味,因为每次我添加一个我所有类都需要访问的实用程序对象时,我都必须在任何地方更改构造函数。

我听说解决这个问题的正确方法是创建一个包含所有不同实用程序对象的结构,并将其传递给所有需要访问它的对象(作为参考)。

这是解决此问题的正确方法吗?谢谢!

更新:感谢大家的反馈。经过一些额外的研究,我决定继续使用依赖注入。

7 个答案:

答案 0 :(得分:11)

你可以让你的GlobalState,Log,DAL班级单身:

class GlobalState {
public:
  static GlobalState& getInstance();
protected:
  GlobalState();
  GlobalState(const GlobalState&);
  GlobalState& operator= (const GlobalState&);
private:
  static GlobalState* p_instance;
};

static GlobalState* GlobalState::p_instance = NULL;

/*static*/
GlobalState& getInstance() {
  // TODO: acquire lock if multi-threaded
  if (!p_instance) {                 // first time?
    p_instance = new GlobalState(); // create sole instance
  }
  // TODO: release lock if multi-threaded
  return *p_instance;               // sole instance
}

然后,在你的各种方法中,

Honda::MyMethod() {
  ...
  const GlobalState& my_state = GlobalState::getInstance();
  ...
}

在某些条件下(例如,所有类的构造函数使用相同数量和类型的参数等),您可以进一步简化defining a singleton C++ template的生命(并减少代码重复的数量)。

答案 1 :(得分:6)

您可以使用服务定位器模式。 This article引入了依赖注入(您当前正在使用)和服务定位器。

然而,请考虑这一点:依赖注入的想法是建立一个系统,其中每个组件都有明确的责任,并尽可能减少对其他组件的了解。如果组件需要其他组件来完成其工作,那么这些组件将显式传递给它。这使得组件更易于理解,更可能更正确,更易于维护。

如果您经常需要添加整个系统中需要知道的组件,那么系统的设计可能会出现问题(或者新功能的添加方式)。依赖注入模式只会导致此问题明确可见。

答案 2 :(得分:2)

我想说工厂有静态类方法来根据需要创建对象 - 如果他们自己不保持状态 - 可能是一个更好的解决方案。如果在任何地方都需要对象并且需要保持全局状态,那么使用Singleton模式可能是合理的。我真的需要知道工厂方法和根据需要重新创建对象在我看单身之前是行不通的。使用Singleton会使您的测试工作变得复杂。

答案 3 :(得分:1)

将状态对象变为单例的好处是你不再需要将const引用传递给所有构造函数了。

因此,如果你的全局状态被Vlad R建议定义,你可以在构造函数(和其他地方)中使用,例如:

来引用它。
GlobalState::getInstance()

因此删除构造函数的参数以及成员变量,使您的接口更清晰。

答案 4 :(得分:1)

我为大多数全局状态对象使用全局命名的实例。该模式类似于传统的单例,除了使用单例,纯粹主义者将坚持其构造函数也是私有的以防止独立构造,而我的模式允许必要的独立构造(即:我的单例模板不需要单例类的构造函数是私人的)。否则,这种模式与弗拉德写的相似。

要注意的一件事是:如果你需要在程序退出时取消分配你的单身人士(例如,你有强制要求你没有泄漏你分配的内存),那么处理可能非常快。描述我不得不捣乱的所有事情,试图使用单例来实现没有内存泄漏会占用很多空间,而且其中许多并不漂亮;因此,如果您需要清理,请考虑使用简单的全局变量(因为方法上可能会令人反感)。

答案 5 :(得分:1)

答案 6 :(得分:0)

要回答你的问题,迈克尔,在这种情况下你可以做到四种不同的事情:

  1. 将所有实用程序对象变为全局变量。
  2. 将所有实用程序类更改为Singletons。
  3. 使用服务定位器。
  4. 使用依赖注入(您已经在做)
  5. 让我们解决前三个选项:

    1. 使用全局变量可能很方便,但它隐藏了对象依赖性,使得单独进行测试变得更加困难。
    2. It's not a good idea to use Singletons.
    3. It's not a good idea to use a Service Locator.
    4. 因此,keep using Dependency Injection