c++ - C++ Google Mock 指南提到的依赖注入(inject)

标签 c++ dependency-injection

在此上下文 ( Google Mock ) 中,依赖注入(inject)(控制反转)是什么意思:

Let's look at an example. Suppose you are developing a graphics program that relies on a LOGO-like API for drawing. How would you test that it does the right thing? Well, you can run it and compare the screen with a golden screen snapshot, but let's admit it: tests like this are expensive to run and fragile (What if you just upgraded to a shiny new graphics card that has better anti-aliasing? Suddenly you have to update all your golden images.). It would be too painful if all your tests are like this. Fortunately, you learned about Dependency Injection and know the right thing to do: instead of having your application talk to the drawing API directly, wrap the API in an interface (say, Turtle) and code to that interface:

class Turtle {
  ...
  virtual ~Turtle() {}
  virtual void PenUp() = 0;
  virtual void PenDown() = 0;
  virtual void Forward(int distance) = 0;
  virtual void Turn(int degrees) = 0;
  virtual void GoTo(int x, int y) = 0;
  virtual int GetX() const = 0;
  virtual int GetY() const = 0;
};

通过类在应用程序代码和绘图API之间添加一层与DI有什么关系?在许多有关依赖注入(inject)的Java示例中,通常不应在类内部具体创建对象。相反,它应该在别处创建以分离两个对象之间的实现耦合。例如(来源 codeproject ):

enter image description here

解决方法:

enter image description here

当我在 Stackoverflow 上搜索有关 DI 的答案时,通常会在 Java 的上下文中询问。一些示例使用了 Java GUI。通常这些例子是如此简单和明显,以至于我看不出它的意义,除了更好的设计和更少的耦合。然而,我要学习的是它背后的意义。如 wiki 中所定义, 控制反转 (IoC) 意味着您反转代码的控制流。那么,它如何适用于 Google 案例?与程序风格相比,实际流程如何倒转?我以为代码是从上到下逐行顺序执行的,而不是从下到上?

最佳答案

维基百科对这些有很好的定义:

  1. http://en.wikipedia.org/wiki/Inversion_of_control
  2. http://en.wikipedia.org/wiki/Dependency_injection

依赖注入(inject)只是类通过接口(interface)(图形 API)与另一个类交互的一种奇特方式,它提供了一种改变接口(interface)指向的方式(即注入(inject)对另一个类的依赖)。

对于控制反转,维基百科提到了工厂模式之类的东西。

它还提到了 setter 注入(inject)(使用 setter 函数更改接口(interface)实现)、构造注入(inject)(从构造函数设置接口(interface)实现)或接口(interface)注入(inject)(从另一个接口(interface)请求接口(interface)实现)并指出这些是依赖类型注入(inject)。

这就是这里发生的事情——程序可以使用 setter 方法(控制反转)更改海龟程序的绘图 API(依赖注入(inject))。

这允许你有一个像这样的测试类:

struct DrawingTester : public DrawingInterface
{
    void move_to(long x, long y) { printf("moveto %d %d\n", x, y); }
    void line_to(long x, long y) { printf("lineto %d %d\n", x, y); }
};

并通过测试程序驱动它:

int main(int argc, char **argv) {
    DrawingTester drawing;
    Turtle t;
    t.setDrawingApi(&drawing);
    t.runProgramFromFile(argv[0]);
    return 0;
}

然后您可以使用 DrawingTester 的预期输出来测试 turtle/logo 测试程序。例如:

# test1.logo

MOVE 5, 7

# test1.calls

moveto 5 7

并通过测试套件(例如 https://github.com/rhdunn/cainteoir-engine/blob/master/tests/harness.pyhttps://github.com/rhdunn/cainteoir-engine/blob/master/tests/metadata.py)驱动它。

关于c++ - C++ Google Mock 指南提到的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8678017/

相关文章:

c++ - 跨线程从 QML 调用 QObject 函数

c++ - 默认情况下 Constexpr lambda?

java - Spring XML 配置 - 如何指定一组对象的属性值?

java - 单例注入(inject)拦截器多个实例化

java - 简单的依赖注入(inject)不起作用

c++ - 我可以在 C++ 类中声明 "using namespace"吗?

c++ - 编译使用 spidermonkey 的程序时出现链接器错误

c++ - libpng 在 png_write_into 上崩溃(Windows 10,VS2013,自建,所有测试通过 ok)

.net - 使用 .NET Core 进行 DAL 和连接字符串的依赖注入(inject)

design-patterns - 如何向一个 5 岁的 child 解释依赖注入(inject)?