简体   繁体   English

有关C ++中的依赖注入的几个问题

[英]Several questions regarding Dependency Injection in C++

I am practicing dependency injection and there are several issues that i am not sure how to deal with them. 我正在练习依赖项注入,但是我不确定有几个问题如何处理。

  1. class A may be dependant on 3-4 other behaviour (interfaces). A类可能取决于3-4个其他行为(接口)。 On the one hand, passing all of them in the constructor makes the object harder to create and initialize. 一方面,将它们全部传递给构造函数会使对象更难以创建和初始化。 On the other hand, using setters might be problematic in case a client forgot to set one of the dependencies. 另一方面,如果客户端忘记设置一个依赖项,则使用setter可能会出现问题。 What would be the correct way to deal with this? 解决这个问题的正确方法是什么?

  2. Eventually, all dependencies must be created somewhere. 最终,所有依赖项都必须在某个地方创建。 How do i prevent a case in which i have many initialization in one class (for example, the main class) ? 如何防止在一个类(例如主类)中进行多次初始化的情况?

  3. Is it considered a good practice to use shared_ptr when doing dependency injection? 在进行依赖注入时,使用shared_ptr是否被视为一种好习惯? In such cases the creator of the dependencies usually could not delete the objects, so it makes sense to me to use shared pointers. 在这种情况下,依赖关系的创建者通常无法删除对象,因此使用共享指针对我来说很有意义。

class A may be dependant on 3-4 other behaviour (interfaces). A类可能取决于3-4个其他行为(接口)。 On the one hand, passing all of them in the constructor makes the object harder to create and initialize. 一方面,将它们全部传递给构造函数会使对象更难以创建和初始化。 On the other hand, using setters might be problematic in case a client forgot to set one of the dependencies. 另一方面,如果客户端忘记设置一个依赖项,则使用setter可能会出现问题。 What would be the correct way to deal with this? 解决这个问题的正确方法是什么?

There's no perfect solution, so you just have to tune to taste. 没有完美的解决方案,因此您只需要调整即可品尝。 Options include: 选项包括:

  • having the/a constructor accept a structure grouping the injected objects (if you're passing the same set of dependencies to many constructors) 让/ a构造函数接受对注入的对象进行分组的结构(如果您将相同的依赖集传递给许多构造函数)

  • dividing dependencies between run-time and compile-time and having compile-time dependencies factored using derivation/ using / typedef ("Policies" ala Modern C++ Design by Alexandrescu) 在运行时和编译时之间划分依赖关系,并使用派生/ using / typedef using考虑编译时的依赖关系(Alexandrescu的“ Policies” ala Modern C ++ Design)

  • providing defaults for some/all dependencies, or some dynamic lookup "service" that still lets you modify the injections but persists across multiple dependent-object constructions 提供某些/所有依赖项的默认值,或提供一些动态查找“服务”的功能,该服务仍可让您修改注入但在多个依赖对象构造中仍然存在

A bit of imagination and analysis of your repetitive code would hopefully suggest an approach to you.... 有点想象力和对重复代码的分析会希望对您有所帮助。

Eventually, all dependencies must be created somewhere. 最终,所有依赖项都必须在某个地方创建。 How do i prevent a case in which i have many initialization in one class (for example, the main class) ? 如何防止在一个类(例如主类)中进行多次初始化的情况?

This is a matter of factoring redundant dependency creation and the access to objects - your choices are similar - passing around references or pointers, using structures or containers or management objects to group them and re-access them.... 这是将冗余依赖关系创建和对象访问(包括您的选择是相似的)之间的关系分解在一起的问题,您可以使用结构或容器或管理对象对引用或指针进行传递,以对它们进行分组并重新访问它们。

Is it considered a good practice to use shared_ptr when doing dependency injection? 在进行依赖注入时,使用shared_ptr是否被视为一种好习惯? In such cases the creator of the dependencies usually could not delete the objects, so it makes sense to me to use shared pointers. 在这种情况下,依赖关系的创建者通常无法删除对象,因此使用共享指针对我来说很有意义。

For functions, often the client code necessarily outlives the use by the function being called so there's no need for shared pointers... a reference is ideal. 对于函数,客户端代码通常必须比被调用的函数使用时间长,因此不需要共享的指针……引用是理想的。 If you're using threads, or creating objects that can outlive the client code, then shared pointers can make a lot of sense. 如果您正在使用线程,或者创建的对象可能超出客户端代码的寿命,那么共享指针会很有用。

All personal opinions, but there we go. 所有个人意见,但我们走了。

1) Pass the dependencies to the constructor. 1)将依赖项传递给构造函数。 If there are sensible defaults, then provide multiple constructors or use default arguments. 如果存在合理的默认值,则提供多个构造函数或使用默认参数。

2) If you're going to be using the same set of dependencies frequently, you might be able to save yourself some typing by creating a "dependency set" class, an instance of which can be passed to a constructor, something like: 2)如果您将频繁使用同一组依赖项,则可以通过创建“依赖项集”类来节省一些键入内容,该类的实例可以传递给构造函数,例如:

struct Iface1;
struct Iface2; // Dependent interfaces
struct Iface3;

struct DependencySet
{
    Iface1& iface1;
    Iface2& iface2;
    Iface3& iface3;
};

class Dependent
{
public:
    Dependent(DependencySet& set)
        : iface1(set.iface1)
        , iface2(set.iface2)
        , iface3(set.iface3)
    {}

private:
    Iface1& iface1;
    Iface2& iface2;
    Iface3& iface3;
};

3) Personally I'd favour using references as above and managing the lifetimes so that the dependencies outlive the dependent class, but shared pointers could be used if you want to "forget" about the dependencies once you've used them. 3)就我个人而言,我更喜欢使用上面的引用并管理生存期,以使依赖项的寿命超过依赖类,但是如果您希望在使用依赖项后就“忘记”它们,可以使用共享指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM