Home > Articles

C++ Interfaces

This chapter is from the book

Dependency injection as a cure

When an object uses a singleton, it injects a hidden dependency into the object. Thanks to dependency injection, this dependency is part of the interface, and the service is injected from the outside. Consequently, there is no dependency between the client and the injected service. Typical ways to inject dependencies are constructors, setter members, or template parameters.

The following program shows how you can replace a logger using dependency injection.

// dependencyInjection.cpp
   
#include <chrono>
#include <iostream>
#include <memory>
   
class Logger {
public:
   virtual void write(const std::string&) = 0;
   virtual ~Logger() = default;
};
   
class SimpleLogger: public Logger {
   void write(const std::string& mess) override {
      std::cout << mess << std::endl;
   }
};
   
class TimeLogger: public Logger {
   using MySecondTick = std::chrono::duration<long double>;
   long double timeSinceEpoch() {
      auto timeNow = std::chrono::system_clock::now();
      auto duration = timeNow.time_since_epoch();
      MySecondTick sec(duration);
      return sec.count();
   }
   void write(const std::string& mess) override {
      std::cout << std::fixed;
      std::cout << "Time since epoch: " << timeSinceEpoch() 
   }
   
};
   
class Client {
public:
   Client(std::shared_ptr<Logger> log): logger(log) {}
   void doSomething() {
      logger->write("Message");
   }
   void setLogger(std::shared_ptr<Logger> log) {
      logger = log;
   }

private:
   std::shared_ptr<Logger> logger;
};
   

int main() {
   
   std::cout << '\n';
   
   Client cl(std::make_shared<SimpleLogger>());    // (1)
   cl.doSomething();
   cl.setLogger(std::make_shared<TimeLogger>());   // (2)
   cl.doSomething();
   cl.doSomething();
   
   std::cout << '\n';
   
}

The client cl supports the constructor (1) and the member function setLogger (2) to inject the logger service. In contrast to the SimpleLogger, the TimeLogger includes the time since epoch in its message (see Figure 3.1).

Figure 3.1

Figure 3.1 Dependency injection

InformIT Promotional Mailings & Special Offers

I would like to receive exclusive offers and hear about products from InformIT and its family of brands. I can unsubscribe at any time.