Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to handle multiple object dependencies in C++?

Tags:

c++

I'm building a C++ application, and I've got several utility objects that all of my classes need to use. These are things like the logging object, the global state object, the DAL object, etc...

Up until this point, I've been passing all of these objects around as references into my class constructors.

For example:

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;
}

This gets tedious fast, because each time I add a utility object that all of my classes need to access, I have to go and change the constructors everywhere.

I've heard that the correct way to solve this problem is to create one struct that contains all the different utility objects and pass that around (as a reference) to all of the objects that need to access it.

Is this the right way to handle this problem? Thanks!

UPDATE: Thank you to everyone for the feedback. After some additional research, I've decided to continue using Dependency Injection.

like image 975
Runcible Avatar asked Feb 20 '09 23:02

Runcible


2 Answers

You can make your GlobalState, Log, DAL classes singletons:

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
}

Then, inside your various methods,

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

You can further simplify your life (and reduce the amount of code duplication) by defining a singleton C++ template, under certain conditions (e.g. all classes' constructors take the same number and types of arguments, etc.)

like image 96
vladr Avatar answered Nov 15 '22 04:11

vladr


You could make use of the Service Locator pattern. This article introduces both dependency injection (which you are currently using) and service locator.

However, consider this: the idea of dependency injection is to have a system where each component has a well-defined responsibility and minimizes knowledge of other components where possible. If the component needs other components to do its job, then these are explicitly passed to it. This makes the component simpler to understand, more likely to be correct, and easier to maintain.

If you regularly need to add components which need to be known throughout the system, then there may be something wrong with the design of the system (or the way new features are being added to it). The dependency injection pattern just results in this problem being explicitly visible.

like image 42
Wim Coenen Avatar answered Nov 15 '22 06:11

Wim Coenen