工厂设计模式和弹簧

我想知道在使用依赖注入的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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章