我想知道在使用依赖注入的Spring框架的上下文中使用工厂模式的当前最佳实践是什么。考虑到使用Spring依赖注入,如今的工厂模式是否仍然有用,我感到奇怪。我进行了一些搜索,看到了一些以前的讨论(Dependency Injection vs Factory Pattern),但似乎有不同的看法。
我在一个现实生活中的项目中看到使用Map来容纳所有bean,并依靠自动装配来创建这些bean。当需要bean时,它使用键通过地图获取它。
public abstract class Service {
//some methods
}
@Component
public class serviceA extends Service {
//implementation
}
@Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
但是我看到这两种方法之间存在一些差异。
使用上述方法,将在应用程序启动时创建所有bean,并由框架处理对象的创建。这也意味着每种类型只有一个bean。
对于工厂模式,工厂类根据请求创建对象。它可以为每个请求创建一个新对象。
我认为可能有一个更深层的问题,当在项目中使用Spring框架时,是否应努力不在类内创建任何对象,这意味着不应使用工厂模式(或任何创建性设计模式?),因为Spring应该是对象依赖项的中央处理程序?
这个问题的答案可能是非常广泛的,我将尝试提供一些希望对您有所帮助的观点。
首先,spring将其bean(子集)存储在ApplicationContext中。本质上,这就是您正在谈论的地图。简而言之,它允许按名称,类型等获取bean。
虽然ApplicationContext是一个非常重要的概念,但它并不是整个Spring的组成部分,实际上Spring框架提供了更大的灵活性:
您说的是,使用映射意味着将在应用程序的开头创建所有bean,并且有bean的一个实例。
Spring有一个懒豆概念,基本上支持仅在第一次需要时才实际创建的bean概念,因此Spring支持“延迟” bean初始化
Spring还允许每种类型的bean包含多个实例。因此,此地图更加“高级”。例如,您可以创建该接口的多个实现,并使用声明均为bean的方式。只要您提供了有关应将哪种bean注入可能使用它们的类的足够信息(例如,在春季提供的限定符的帮助下),您就可以开始使用。此外,spring IoC容器中还具有一些功能,可以将接口的所有已注册实现注入到列表中:
interface Foo {}
@Component
class FooImpl1 implements Foo {}
@Component
class FooImpl2 implements Foo {}
class Client {
@Autowired
List<Foo> allFoos;
}
现在您说:
对于工厂模式,工厂类根据请求创建对象。它可以为每个请求创建一个新对象。
实际上,Spring可以根据请求创建对象。并非所有的bean都必须是单例的,通常来说spring具有用于此目的的作用域概念。
例如,作用域原型意味着Spring将在每次使用时创建一个bean。弹簧特别支持多种有趣的用法,就是将原型bean注入singleton。一些解决方案的使用就像工厂一样(了解注释,@Lookup
其他解决方案则依赖于运行时自动生成的代理(如javax.inject.Provider
)。原型作用域bean不保存在应用程序上下文中,因此spring不再局限于简单的映射抽象。
您没有提到的最后一个功能是,有时甚至对于单例来说,初始化也可能比使用Parameters调用构造函数要复杂一些。Spring可以使用Java配置解决此问题:
@Configuration
public class MyConfig {
public SomeComplicatedObject foo(@Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
foo
这里的方法初始化对象SomeComplicatedObject
并返回它。可以使用它代替工厂来集成“旧版”代码(很好,java配置超出了此范围,但是超出了此问题的范围)。
因此,最重要的是,作为IoC容器的Spring可以提供许多不同的方式来处理对象创建,特别是它可以完成工厂设计模式所提供的一切。
现在,我还要参考一下您的最后一句话:
我认为可能有一个更深层的问题,当在项目中使用Spring框架时,是否应努力不在类内创建任何对象,这意味着不应使用工厂模式(或任何创建性设计模式?),因为Spring应该是对象依赖项的中央处理程序?
的确,使用Spring时不必使用Factory Pattern,因为(正如我希望的那样,因为)提供了Factory可以做的一切以及更多工作。
我也同意应将spring作为对象依赖项的中央处理程序(除非应用程序的某些部分以不同的方式编写,因此您必须同时支持这两种方法:))
我认为我们不应该完全避免使用“新的”,不是所有的东西都应该/可以是一个豆子,但是我确实(从我的主观经验来看,这是有争议的)确实减少了您的使用,而留下了大部分的Spring的对象。
我们应该避免使用任何创作设计模式吗?我不这么认为,有时您可以选择实现“构建器”设计模式,例如,它也是一种创建模式,但是spring没有提供类似的抽象。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句