简体   繁体   English

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

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

Im looking to this example to understand the use of factory pattern. 我正在看这个例子,以了解工厂模式的使用。

I'm really amator in this field so excuse my silly question. 我真的是这个领域的专家,所以请原谅我这个愚蠢的问题。

My problem is that i don't see the use of the factory pattern which return us the interface that we can inject it directly when we need to use it. 我的问题是我看不到工厂模式的使用,该模式返回给我们接口,我们可以在需要使用它时直接注入它。

In the example above I would do something like this: 在上面的示例中,我将执行以下操作:

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;
    }
}

Instead of injecting the factory : 而不是注入工厂:

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;
    }
}

Why taking the bruden to create a factory (thus adding an extra layer) when we can inject the interface directly to wherever we need to use it ? 当我们可以将接口直接注入到需要使用它的任何地方时,为什么还要花大笔钱创建一个工厂(从而增加一个额外的层)?

I think you don't want just another article about the factory pattern but a short comprehensive answer. 我想您不希望只想再写一篇有关工厂模式的文章,而不仅仅是一个简短的综合答案。 So, I'd like to focus on two things. 因此,我想重点关注两件事。

More flexibility 更大的灵活性

Most commonly, you'd set up your composition root where you basically say ... 最常见的是,您会在基本上说的地方设置合成根目录...

"if anyone wants IAnyService , he should get MyAnyServiceImplementation ". “如果有人想要IAnyService ,他应该获得MyAnyServiceImplementation ”。

This is fixed for your application. 这对于您的应用程序是固定的。 Once set up, your dependency injection container will serve the class instances you registered but you should not try to re-configure that container again. 设置完成后,您的依赖项注入容器将为您注册的类实例提供服务,但您不应尝试再次重新配置该容器。 That's perfect for startup flexibility like registering implementation for data access components by the application's configuration, for example. 这非常适合启动灵活性,例如通过应用程序的配置为数据访问组件注册实现。 Say ... 说...

"if anyone wants IUserRepository , he should get MsSqlUserRepository because we are working with MSSQL server". “如果有人想要IUserRepository ,他应该得到MsSqlUserRepository因为我们正在使用MSSQL服务器”。

Of course, having that "immutable" composition root limits the possibilities to choose an implementation in runtime depending of the applications' state. 当然,具有“不可变”的构成根将限制在运行时根据应用程序状态选择实现的可能性。

Instead you can inject a class which decides on a current state which service implementation to choose. 相反,您可以注入一个类,该类决定当前状态以选择哪种服务实现。 Data validation is a typical scenario for that pattern because there might be different rules for different entities on your system. 数据验证是该模式的典型场景,因为系统上不同实体的规则可能不同。 The buzzword here is "rule pattern" or "strategy pattern". 这里的流行词是“规则模式”或“策略模式”。

Lifetime control 终身控制

Think of a long-living class instance like a view (user interface) or any class attached to it (like a viewmodel or a controller). 可以将一个长期存在的类实例视为一个视图(用户界面)或与其相连的任何类(例如一个视图模型或控制器)。 As long as a user is active on a view, the class is alive. 只要用户在视图上处于活动状态,该类就处于活动状态。 By injecting a class instance to the constructor of the view controller, for example, you hold an active instance of it as long as the view lives. 例如,通过将一个类实例注入到视图控制器的构造函数中,只要视图存在,就可以持有它的活动实例。

Let's say you want to use a data repository to connect to a database for example. 例如,假设您要使用数据存储库连接到数据库。 These database access calls should be short and you do not want to keep connections open for a long time. 这些数据库访问调用应该很短,并且您不想长时间保持打开状态。 With a repository factory, you could control the lifetime very precisely and make sure that the class is removed after it has been used: 使用存储库工厂,您可以非常精确地控制生存期,并确保在使用该类后将其删除:

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

With this, a very lightweight class - the factory - gets injected and lives as long as the view controller lives. 这样,只要视图控制器有效,就可以注入并存活一个非常轻量级的类-工厂。 The heavy classes - the connection things - should not live long and are just created when needed. 繁重的类-连接事物-不应长期存在,仅在需要时创建。

In fact, chances are that the repository is not instantiated at all if there's no requirement to load the data (because of an upfront cache hit, for example). 实际上,如果不需要加载数据,则很有可能根本不会实例化存储库(例如,由于前期缓存命中)。 If you would have injected the repository directly, you'd guarantee that one long living instance lives in memory in every case. 如果您将直接注入存储库,则可以保证在每种情况下内存中都存在一个长期存在的实例。

If you check the code for the factory you can see that depending on the ShippingMethod of the order a different implementation of the IShippingStrategy is returned by the factory. 如果检查工厂代码,则可以看到,根据订单的ShippingMethod,工厂将返回IShippingStrategy的不同实现。 Since the ShippingMethod is only known once DoTheWork has been called it's impossible to inject the right implementation when the class is constructed (and the same class might even need different implementations for different orders). 由于仅在调用DoTheWork之后才知道ShippingMethod,因此在构造类时不可能注入正确的实现(并且同一类甚至可能需要针对不同顺序的不同实现)。

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

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