【问题标题】:Relation of Singleton pattern with dependency injection单例模式与依赖注入的关系
【发布时间】:2012-02-29 19:21:52
【问题描述】:

从这里:http://www.codingwithoutcomments.com/

如果你确实使用单例,请尝试使用依赖注入而不是 从构造函数调用 getInstance(),使用这个:

public MyConstructor(Singleton singleton) 
{
     this.singleton = singleton; 
} 

而不是这样:

public MyConstructor() 
{
     this.singleton = Singleton.getInstance(); 
}

至少,使用依赖注入允许您通过遵循良好的封装原则对类进行一些单元测试。

这个“依赖注入”如何?依赖注入是什么意思?
这不是违背了单例模式的目的吗?

这是否应该使用一段时间然后删除?

【问题讨论】:

标签: c++ design-patterns


【解决方案1】:

您提供的代码没有区别,而且它不是依赖注入,因为您将单例按值传递给构造函数(这是构造函数,对吗?)。

如果必须使用单例,则使用引用将其管理的对象传递给构造函数:

struct Abase
{
};
struct A : Abase // object of this type is created in the singleton
{
};

struct B
{
  B(Abase &a_) : a(a_)
  {
  }

private:
  Abase & a;
};

//...
B b( Singleton.getInstance() );
//...

【讨论】:

  • here are no differences in the codes you provided 我发布了链接。这不是我自己写的。错了吗?
  • 我不同意。第一个示例实际上使依赖注入成为可能(因为它提供了一个构造函数参数来获取单例实例),而第二个则没有。
  • 你可能不会打电话给B b(Singleton.getInstance())(而且问题并没有说明它确实如此)。你会调用B b(instance),因为调用者要么是可以直接访问实例的工厂,要么是另一个本身通过依赖注入获得引用的对象。
  • 从语法(但不是问题标签)来看,我猜测语言是 C# 或 Java,所以参数是通过引用传递的。
  • @NiklasB。这取决于单例的实现。它必须返回不同的对象,具体取决于它是在应用程序中使用,还是用于单元测试的模拟。除此之外,还有不同种类的依赖注入。
【解决方案2】:

这个“依赖注入”是怎么回事?

“依赖注入”意味着你显式地为一个对象提供了对它所依赖的所有其他对象的引用;这就是第一个示例在将引用传递给构造函数时所做的事情。

另一种方法是隐式提供它所依赖的对象,方法是使它们全局可访问。这就是第二个示例的作用。

依赖注入的主要优点是依赖可以在抽象接口上;无需将您的类与特定的具体类或该类的特定实例联系起来。这使测试更加方便——您的类可以单独测试,与它所依赖的任何接口的“存根”实现进行交互。它还可以更轻松地跟踪依赖关系,因为它们都在代码中明确说明。

使用全局变量的主要优点是它们允许您编写的代码稍微少一些,并且在它们成为问题之前您无需担心管理依赖关系;当他们这样做时,您可以简单地放弃该项目并开始一个新项目。

这不是违背了单例模式的目的吗?

这取决于你认为反模式的目的是什么。它确实消除了全局可访问实例的便利性。但是,假设 Singleton 类确实遵循反模式,您仍然可以确保收到的对​​象是 One True Instance。

这是否应该使用一段时间然后删除?

一旦你需要做反模式阻止的事情(单元测试、多实例、子类型、抽象接口等),单例应该被一个普通的类替换,通过引用传递给它的依赖项。一旦存在依赖注入,就几乎不需要删除它;一旦发现单例不符合您的要求,您只需将其重新放回即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多