Última actualización:2026-10-12
C++ Inyección de dependencias¶
Hace poco, un miembro del Planeta de Conocimiento me pidió que tratara la inyección de dependencias, así que escribí este artículo, que parte de un ejemplo práctico: se explican los principios y la implementación; el código completo de la versión abreviada está en el Planeta de Conocimiento. Vamos al lío.
Esquema:
- Dependencia directa
- Inyección de dependencias por interfaz
- Inyección de dependencias por plantillas
La inyección de dependencias es un patrón de diseño muy usado; normalmente se emplean interfaces o plantillas para mejorar la testeabilidad y el mantenimiento del código. Veámoslo con un ejemplo.
Supongamos una clase de servicio de usuarios UserService que necesita comunicarse con un servidor remoto a través de un cliente HTTP; en este caso podríamos escribir las tres implementaciones siguientes.
1.Dependencia directa¶
UserService depende internamente de HttpClient directamente, por ejemplo:
class HttpClient {
public:
std::string Get(const std::string& url);
void Post(const std::string& url, const std::string& data);
};
class UserService {
private:
HttpClient m_httpClient;
};
Dentro de UserService normalmente habrá métodos que operan sobre m_httpClient; este enfoque es simple y directo, pero UserService queda acoplado al HttpClient concreto, lo que dificulta sustituir el objeto dependiente y también hacer pruebas unitarias.
De ahí surgen los dos métodos siguientes.
2.Inyección de dependencias por interfaz¶
Nuestro objetivo es que las pruebas resulten cómodas, sin necesidad de crear una clase concreta: que el usuario pueda hacer mock de una clase para probar. Para ello podemos pensar en una interfaz: extraemos HttpClient y obtenemos:
struct IHttpClient {
virtual std::string Get(const std::string& url) = 0;
virtual void Post(const std::string& url, const std::string& data) = 0;
virtual ~IHttpClient() = default;
};
class UserService {
private:
std::unique_ptr<IHttpClient> m_httpClient;
};
Así, a la hora de probar se puede hacer mock de un client y probar con él, por ejemplo:
class MockHttpClient : public IHttpClient {
public:
MOCK_METHOD(std::string, Get, (const std::string& url), (override));
MOCK_METHOD(void, Post, (const std::string& url, const std::string& data), (override));
};
auto mockHttpClient = std::make_unique<MockHttpClient>();
UserService userService(std::move(mockHttpClient));
Tras esta refactorización podemos conseguir:
- Ocultar los detalles de implementación en el archivo .cc
- Trabajar contra una interfaz abstracta
- Inyectar las dependencias durante la construcción del objeto
3.Inyección de dependencias por plantillas¶
La inyección de dependencias por plantillas usa las técnicas de plantillas de C++ para pasar el objeto dependiente como parámetro de plantilla a UserService. Al instanciar la plantilla se especifica la implementación concreta del cliente HTTP. Este enfoque resuelve la dependencia en tiempo de compilación, sin llamadas a funciones virtuales, lo que mejora el rendimiento. Además, permite que la clase UserService se integre con flexibilidad con distintas implementaciones de clientes HTTP y facilita las pruebas unitarias.
En este caso resulta sencillo de probar, por ejemplo:
Este enfoque tiene las siguientes ventajas:
- Las dependencias se inyectan durante la instanciación de la plantilla
- No hay llamadas virtuales (nótese que THttpClient no es una interfaz, por lo que las llamadas pueden resolverse en tiempo de compilación)
Esto es todo el contenido de esta sección; el código completo está en el Planeta de Conocimiento, ¡suscríbete para descargarlo!
Temas relacionados¶
- C++ Evitar el constructor por defecto | C++那些事
- C++ Idioma de la lista de inicialización de clases | C++那些事
- C++: plantillas de clase antes que plantillas de función | C++那些事
- C++ Idioma copy-and-swap | C++那些事
- C++ enum class enumeraciones fuertemente tipadas | C++那些事
- C++ Header-Only frente a separación de implementación | C++那些事
- C++ Idioma de evaluación perezosa | C++那些事
- C++ Idioma de la tabla de consulta | C++那些事
- C++ Punteros a miembros e información de tipos | C++那些事
- C++ Idioma mixin | C++那些事