What is so bad about singletons?
已经清楚地解释了Singleton设计模式违反了多个最佳实践。那么为什么Spring beans默认是单身?这种设计不会间接导致相同的违规行为吗?
答案 0 :(得分:11)
单例模式和弹簧单例几乎没有共同之处。实际上唯一的可能是:
生产中只有一个实例
让我们通过你所链接答案的模式评论:
它们通常用作全局实例,为什么这么糟糕?因为您在代码中隐藏了应用程序的依赖关系,而不是通过接口公开它们。制作一些全局的东西以避免传递它是一种代码味道。
使用Spring,你正好相反。你只是说:"我需要其中一个,而不关心它来自哪里。"
他们违反了单一责任原则:由于他们控制着自己的创造和生命周期。
再次:Spring完全相反:你编写一个普通的pojo,然后在Spring配置中配置它应该具有的生命周期。
它们固有地导致代码紧密耦合。在许多情况下,这使得将它们伪装在测试中相当困难。
使用Spring,没有什么能阻止你为每个测试使用不同的实例。
它们在应用程序的生命周期中携带状态。测试的另一个打击因为你可能最终会遇到需要订购测试的情况,这对于单元测试来说是一个很大的问题。为什么?因为每个单元测试应该独立于另一个。
是的,他们可以在应用程序的生命周期内携带状态,但由于您可以选择更改测试中的生命周期或实现(或应用程序的不同实例),因此测试保持彼此独立。
这一切并非特定于Spring,但对于所有成熟的依赖注入框架都是如此,即使您选择手动执行它也是如此。
答案 1 :(得分:2)
Spring Singletons并不是真正的单身人士,因为我们从GOF设计模式中了解它们。 它们给你这种感觉,因为IoC容器(Bean Factory)会有一个bean。
这意味着您可以实例化一个为其创建单例bean的类。
你也可以有两个来自同一个班级的单身豆。
所以,'奇点'是bean工厂中bean的概念,而不是类。
示例:
@Configuration
public class AppConfig {
@Bean(name = "a")
public MyBeanClass a() {
return new MyBeanClass();
}
@Bean(name = "b")
public MyBeanClass b() {
return new MyBeanClass();
}
}
因此,您将拥有2个MyBeanClass类的单例bean。 MyBeanClass不是设计模式的单例。