专业的编程技术博客社区

网站首页 > 博客文章 正文

工厂依赖注入(工厂模式和依赖注入的区别)

baijin 2024-09-06 14:53:13 博客文章 4 ℃ 0 评论

另一种可供考虑的选择

介绍

在 Java 中,我们有不同的方法来初始化对象。它可以是正常初始化、依赖注入或工厂模式。

在 Spring 框架中,依赖注入是通常用于允许组件松散耦合的基本方面,而无需知道每个组件的依赖关系。

同样,工厂模式也促进了组件的松散耦合,因为它将了解的需求委托给了工厂。


依赖注入与工厂模式

依赖注入和工厂模式的区别在于实例的生命周期管理。

对于依赖注入,生命周期管理由代码外部的框架处理。

对于工厂模式,生命周期管理由应用程序内的程序员处理。


什么是工厂的依赖注入?

基于工厂模式的对象创建决策逻辑仍然是依赖注入。

让我们看一个例子。假设我们有两个类,InstanceDelivery 和 ScheduledDelivery,它们在创建订单时执行不同的逻辑。

interface IDelivery{
    fun createOrder()
}
@Service
class InstantDelivery():IDelivery{
    override fun createOrder(){
        // create delivery record 
        ...
        ...
    }
}
@Service
class ScheduledDelivery(
    val scheduler: Scheduler,
):IDelivery{
    override fun createOrder(){
        // check before create
        if(scheduler.check()){
            // create delivery record 
            ...
            ...
        }
    }
}


只是依赖注入

仅使用依赖注入,它的好处是显而易见的。

  • 首先,使用构造函数注入创建对象很简单。
  • 其次,对象的创建对于具有多个实例的类来说更加透明。 例如,ScheduledDelivery 类依赖于 Scheduler 类。

但是,构造函数注入也有缺点。

  • 首先,它会导致一种称为长参数列表的代码异味。 在此示例中,只有 2 种交付方式(即时和计划),因此看起来可以接受。 但是,如果有 10 种交付方式怎么办?
  • 其次,只要引入了额外的交付模式,构造函数签名就容易发生变化。 似乎构造函数签名更改不会影响任何具有依赖注入的代码。 但是,如果您在单元测试中注入模拟对象,它们将影响 DeliveryService 类的单元测试。
@Service
class DeliveryService(
    val instantDelivery: InstantDelivery,
    val scheduledDelivery: ScheduledDelivery,
){
    fun process(val mode: String) {
        ....
        ....

        when (mode){
            "INSTANCE" -> instantDelivery.createOrder()
            "SCHEDULED" -> scheduledDelivery.createOrder()
            else -> throw Exception("Not supported")
        }
    }
}


只是工厂模式

仅使用工厂模式,对象的创建不像依赖注入那么简单。

首先,您需要了解每个类的依赖关系,在其中创建对象可能会很乏味。

其次,DeliveryService 类的单元测试更难构建,因为 DeliveryFactory 不可模拟。

但是,工厂模式的好处是减少了依赖构造函数注入导致的长参数列表。

class DeliveryFactory(){
  companion object{
    fun getInstance(mode: String) : IDelivery{
        return when (mode){
            when (mode){
                "INSTANCE" -> InstantDelivery()
                "SCHEDULED" -> ScheduledDelivery(Scheduler())
                else -> throw Exception("Not supported")
            }
        }
    }
  }
}
@Service
class DeliveryService(){
    fun process(val mode: String) {
        ....
        ....

        DeliveryFactory.getInstance(mode).createOrder()
    }
}


工厂依赖注入

通过工厂的依赖注入,它结合了两者的优点,同时消除了缺点。

首先,对象的创建是透明的。

其次,长参数列表从许多减少到 1。

第三,不易发生构造函数签名更改。

第四,单元测试更容易,因为它是可模拟的。

基于的实现仍然是依赖注入,其中 DeliveryService 和 DeliveryFactory 使用构造函数注入。 DeliveryFactory 中的 getInstance 实现了对象创建决策逻辑以返回所需的对象。

@Component
class DeliveryFactory(
    val deliveryList: List<IDelivery>
){
    fun getInstance(mode: String) : IDelivery{
        return when (mode){
                "INSTANCE" -> deliveryList.filterIsInstance<InstantDelivery>().first()
                "SCHEDULED" -> deliveryList.filterIsInstance<ScheduledDelivery>().first()
                else -> throw Exception("Not supported")
            }
        }
    }
}
@Service
class DeliveryService(
    val deliveryFactory : DeliveryFactory
){
    fun process(val mode: String) {
        ....
        ....

        deliveryFactory.getInstance(mode).createOrder()
    }
}


结论

仅依赖注入或工厂模式实现没有任何问题。 使用工厂的依赖注入增加了另一种选择,以使您的代码更清晰和有条理。 当您拥有 2 个以上的服务等级时,它更适合,并且随着它的增长,这种技术的好处会更大。 最终,使用适合用例的任何设计模式都很重要。

这就是短篇阅读的全部内容。 谢谢你的时间

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表