繁体   English   中英

简单的依赖注入就足够了,为什么要使用工厂模式

[英]Why using the factory pattern when a simple dependecy injection is enough

我正在看这个例子,以了解工厂模式的使用。

我真的是这个领域的专家,所以请原谅我这个愚蠢的问题。

我的问题是我看不到工厂模式的使用,该模式返回给我们接口,我们可以在需要使用它时直接注入它。

在上面的示例中,我将执行以下操作:

public class Program
{
    // register the interfaces with DI container in a separate config class (Unity in this case)
    private readonly IShippingStrategy _shippingStrategy;

    public Program(IShippingStrategy shippingStrategy)
    {
        _shippingStrategy= shippingStrategy;
    }

    public int DoTheWork(Order order)
    {
        // assign properties just as an example
        order.ShippingMethod = "Fedex";
        order.OrderTotal = 90;
        order.OrderWeight = 12;
        order.OrderZipCode = 98109;

        int shippingCost = _shippingStrategy.CalculateShippingCost(order);

        return shippingCost;
    }
}

而不是注入工厂:

public class Program
{
    // register the interfaces with DI container in a separate config class (Unity in this case)
    private readonly IShippingStrategyFactory _shippingStrategyFactory;

    public Program(IShippingStrategyFactory shippingStrategyFactory)
    {
        _shippingStrategyFactory = shippingStrategyFactory;
    }

    public int DoTheWork(Order order)
    {
        // assign properties just as an example
        order.ShippingMethod = "Fedex";
        order.OrderTotal = 90;
        order.OrderWeight = 12;
        order.OrderZipCode = 98109;

        IShippingStrategy shippingStrategy = _shippingStrategyFactory.GetShippingStrategy(order);
        int shippingCost = shippingStrategy.CalculateShippingCost(order);

        return shippingCost;
    }
}

当我们可以将接口直接注入到需要使用它的任何地方时,为什么还要花大笔钱创建一个工厂(从而增加一个额外的层)?

我想您不希望只想再写一篇有关工厂模式的文章,而不仅仅是一个简短的综合答案。 因此,我想重点关注两件事。

更大的灵活性

最常见的是,您会在基本上说的地方设置合成根目录...

“如果有人想要IAnyService ,他应该获得MyAnyServiceImplementation ”。

这对于您的应用程序是固定的。 设置完成后,您的依赖项注入容器将为您注册的类实例提供服务,但您不应尝试再次重新配置该容器。 这非常适合启动灵活性,例如通过应用程序的配置为数据访问组件注册实现。 说...

“如果有人想要IUserRepository ,他应该得到MsSqlUserRepository因为我们正在使用MSSQL服务器”。

当然,具有“不可变”的构成根将限制在运行时根据应用程序状态选择实现的可能性。

相反,您可以注入一个类,该类决定当前状态以选择哪种服务实现。 数据验证是该模式的典型场景,因为系统上不同实体的规则可能不同。 这里的流行词是“规则模式”或“策略模式”。

终身控制

可以将一个长期存在的类实例视为一个视图(用户界面)或与其相连的任何类(例如一个视图模型或控制器)。 只要用户在视图上处于活动状态,该类就处于活动状态。 例如,通过将一个类实例注入到视图控制器的构造函数中,只要视图存在,就可以持有它的活动实例。

例如,假设您要使用数据存储库连接到数据库。 这些数据库访问调用应该很短,并且您不想长时间保持打开状态。 使用存储库工厂,您可以非常精确地控制生存期,并确保在使用该类后将其删除:

using (var repository = new _factory.CreateRepository(...))
{
    return repository.GetAnything();
}

这样,只要视图控制器有效,就可以注入并存活一个非常轻量级的类-工厂。 繁重的类-连接事物-不应长期存在,仅在需要时创建。

实际上,如果不需要加载数据,则很有可能根本不会实例化存储库(例如,由于前期缓存命中)。 如果您将直接注入存储库,则可以保证在每种情况下内存中都存在一个长期存在的实例。

如果检查工厂代码,则可以看到,根据订单的ShippingMethod,工厂将返回IShippingStrategy的不同实现。 由于仅在调用DoTheWork之后才知道ShippingMethod,因此在构造类时不可能注入正确的实现(并且同一类甚至可能需要针对不同顺序的不同实现)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM