工厂模式理解_工厂模式

工厂模式理解

工厂模式是一种创新的设计模式,其目的是提供一个接口,用于创建相关或相关对象的族,而无需指定其具体类。 创建逻辑封装在工厂中,该工厂提供创建逻辑的方法或将对象的创建委托给子类。 客户端不知道接口或类的不同实现。 客户端只需要知道工厂即可用于获取接口实现之一的实例。 客户端与对象的创建是分离的。

通常,工厂模式以单例或静态类的形式实现,因为只需要一个工厂实例。 这样集中了对象的创建。

CDI框架

在Java EE中,我们可以利用CDI框架来创建对象,而无需了解对象创建的详细信息。 这种脱钩是Java EE实现控制反转的方式的结果。 传达的最重要的好处是将较高级别的类别与较低级别的类别分离。 这种解耦使具体类的实现可以更改而不会影响客户端:减少耦合并提高灵活性。

CDI框架本身是工厂模式的实现。 容器在应用程序启动期间创建合格对象,并将其注入到与注入标准匹配的任何注入点中。 客户端不需要知道关于对象的具体实现的任何信息,甚至客户端都不知道具体类的名称。

public class CoffeeMachine implements DrinksMachine {
     // Implementation code
 }

像这样使用它:

@Inject
 DrinksMachine drinksMachine;

在这里,容器创建了CoffeeMachine具体类的实例,根据其接口DrinksMachine进行选择,并在容器找到合格注入点的任何位置进行注入。 这是使用工厂模式的CDI实现的最简单方法。 但是,它不是最灵活的。

消歧

如果我们有多个DrinksMachine接口的具体实现, 将会发生什么?

public class CoffeeMachine implements DrinksMachine {
     // Implementation code
 } 

 public class SoftDrinksMachine implements DrinksMachine {
     // Implementation code
 }

应该注入哪种实现? SoftDrinksMachineCoffeeMachine

@Inject
 DrinksMachine drinksMachine;

容器不知道,因此部署将因“模棱两可的依赖项”错误而失败。

资格赛

那么容器如何区分具体的实现? Java EE为我们提供了一个新工具:限定符。 限定词是自定义注释,用于标记具体的类以及容器要注入对象的位置。

回到我们的Drinks机器以及两个相同类型的CoffeeMachineSoftDrinksMachine的具体类,我们将通过使用两个限定符来区分它们:

@Qualifier
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.FIELD})
 public @interface SoftDrink
@Qualifier
 @Retention(RetentionPolicy.RUNTIME)
 @Target({ElementType.METHOD, ElementType.FIELD})
 public @interface Coffee

我们创建一个限定符名称SoftDrink 。 这将注释SoftDrinksMachine混凝土类,而Coffee将注释CoffeeMachine类。

@Target注释限制了我们可以在哪里使用这些限定符标记注入点,在这种情况下,是在方法和字段注入点上。 具有保留策略RUNTIME的注释可确保注释在运行时可用于JVM。

Target的可能值为:TYPE,METHOD,FIELD,PARAMETER。

正确标注了DrinksMachine接口的两个具体实现。 CoffeeMachine类的注释为@Coffee,SoftDrinksMachine类的注释为@SoftDrink

@Coffee
 public class CoffeeMachine implements DrinksMachine {
     // Implementation code
 }
@SoftDrink
 public class SoftDrinksMachine implements DrinksMachine {
     // Implementation code
 }

现在,您注释注入点。 使用限定符@SoftDrink表示要在容器中注入SoftDrinksMachine类的位置,并使用限定符@Coffee来在容器中注入CoffeeDrinkMachine的位置 。 现在,我们已经向容器明确了应该在哪里注入我们的具体实现,并且部署将成功。

@Inject @SoftDrink
 DrinksMachine softDrinksMachine;
@Inject @Coffee
 DrinksMachine coffeeDrinksMachine;

我们已经了解了Java EE的CDI框架如何实现工厂模式,如何隐藏对象的具体实现并允许创建与使用分离。 我们已经看到了如何使用限定符来选择所需的实现,而无需了解有关对象创建的任何知识。

重要的是要记住,CDI框架只会实例化满足托管Bean规范JSR 299的所有条件的POJO。但是,如果您要注入的对象没有,那意味着我们不能利用CDI怎么办?框架针对不符合要求的类的注入功能。 不,不是。 Java EE为我们提供了一个解决方案。 让我们更深入地研究一下如何使用CDI框架将ANY类型的ANY类注入到注入点中。

生产者方法

Java EE具有称为生产者方法的功能。 这些方法提供了一种实例化方式,因此可用于不符合托管bean规范的注入对象,例如需要使用构造函数参数进行正确实例化的对象。 其值可能会在运行时更改的对象以及其创建需要进行一些自定义初始化的对象,也可以通过生产者方法准备好进行注入。

让我们看一个生产者方法,该方法产生一个用Books对象填充的List。

@Produces
 @Library
 public List<Book> getLibrary(){
     // Generate a List of books called 'library'
     return library;
 }

Book对象列表将被注入到注解点@Library中。

像这样使用它:

@Inject @Library
 List<Books> library;

生产者方法的一个重要特征是它的范围。 这将确定何时调用该方法以及该方法产生的对象将保留多长时间。

默认情况下,生产者方法范围是@DependentScoped 。 这意味着它将继承其客户范围。

我们可以通过扩大范围来进一步扩展此示例。 如果我们对生产者方法@RequestScoped进行注释,则它将对其参与的每个HTTP请求仅调用一次,并持续到请求的持续时间。

@RequestScoped
 @Produces
 @Library
 public List<Book> getLibrary(){
     // Generate a List of books called 'library'
     return library;
 }

可能的范围是:

  • RequestScoped – HTTP请求范围
  • SessionScoped – HTTP会话范围
  • ApplicationScoped –在用户之间共享
  • ConversationScoped –与JSF的交互
  • DependentScoped –默认,从客户端继承

优点:易于实现,没有样板代码,神奇地工作,任何对象都可以注入,按类自动配置

错误:命名注释类型不安全

和丑陋:隐藏对象创建,难以遵循执行流程,IDE应该有所帮助

翻译自: https://www.javacodegeeks.com/2015/12/factory-pattern.html

工厂模式理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值