首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于DI和IoC的工厂方法

基于DI和IoC的工厂方法
EN

Stack Overflow用户
提问于 2015-08-11 19:31:11
回答 6查看 55.1K关注 0票数 59

我熟悉这些模式,但仍然不知道如何处理以下情况:

代码语言:javascript
运行
复制
public class CarFactory
{
     public CarFactory(Dep1,Dep2,Dep3,Dep4,Dep5,Dep6)
     {
     }

     public ICar CreateCar(type)
     {
            switch(type)
            {
               case A:
                   return new Car1(Dep1,Dep2,Dep3);
               break;

               case B:
                   return new Car2(Dep4,Dep5,Dep6);
               break;
            }
     }
}

一般来说,问题在于需要注入的引用量。如果有更多的汽车,情况会更糟。

我想到的第一种方法是在工厂构造函数中注入Car1和Car2,但这与工厂方法背道而驰,因为工厂总是返回相同的对象。第二种方法是注入servicelocator,但它到处都是反模式的。如何解决这个问题?

编辑:

备选办法1:

代码语言:javascript
运行
复制
public class CarFactory
{
     public CarFactory(IContainer container)
     {
        _container = container;
     }

     public ICar CreateCar(type)
     {
            switch(type)
            {
               case A:
                   return _container.Resolve<ICar1>();
               break;

               case B:
                     return _container.Resolve<ICar2>();
               break;
            }
     }
}

可供选择的方法2(由于树中的依赖关系太多而难以使用):

代码语言:javascript
运行
复制
public class CarFactory
{
     public CarFactory()
     {
     }

     public ICar CreateCar(type)
     {
            switch(type)
            {
               case A:
                   return new Car1(new Dep1(),new Dep2(new Dep683(),new Dep684()),....)
               break;

               case B:
                    return new Car2(new Dep4(),new Dep5(new Dep777(),new Dep684()),....)
               break;
            }
     }
}
EN

Stack Overflow用户

发布于 2015-08-11 19:47:28

首先,您有一个混凝土工厂,IoC容器可能是一个替代方案,而不是帮助您的东西。

然后,只需重构工厂,以避免期望工厂构造函数中有一个完整的可能参数列表。这是主要问题--如果工厂方法不需要参数,为什么要传递这么多参数?

我宁愿将特定的参数传递给工厂方法。

代码语言:javascript
运行
复制
public abstract class CarFactoryParams { }

public class Car1FactoryParams : CarFactoryParams
{
   public Car1FactoryParams(Dep1, Dep2, Dep3) 
   { 
      this.Dep1 = Dep1;
      ...
}

public class Car2FactoryParams 
      ...

public class CarFactory
{
    public ICar CreateCar( CarFactoryParams params )
    {
        if ( params is Car1FactoryParams )
        {
            var cp = (Car1FactoryParams)params;
            return new Car1( cp.Dep1, cp.Dep2, ... );
        }
        ...
        if ( params is ...

通过将参数列表封装到特定的类中,您只需让客户端提供特定工厂方法调用所需的这些参数。

编辑:

不幸的是,从你的帖子中还不清楚这些Dep1是什么.以及你如何使用它们。

因此,我建议采用将工厂提供程序与实际工厂实现分开的方法。这种方法称为本地工厂模式:

代码语言:javascript
运行
复制
public class CarFactory
{
   private static Func<type, ICar> _provider;

   public static void SetProvider( Func<type, ICar> provider )
   {
     _provider = provider;
   }

   public ICar CreateCar(type)
   {
     return _provider( type );
   }
}

工厂本身没有任何实现,它是为了为您的域API设置基础,您希望只使用这个API创建car实例。

然后,在复合根中(在配置实际容器的应用程序的起点附近),配置提供程序:

代码语言:javascript
运行
复制
CarFactory.SetProvider(
    type =>
    {
        switch ( type )
        {
           case A:
             return _container.Resolve<ICar1>();
           case B:
             return _container.Resolve<ICar2>();
           ..
    }
);

注意,工厂提供程序的此示例实现使用委托,但接口也可以用作实际提供程序的规范。

这个实现基本上是你编辑的问题中的#1,但是它没有任何特别的缺点。客户仍然打电话给:

代码语言:javascript
运行
复制
var car = new CarFactory().CreareCar( type );
票数 1
EN
查看全部 6 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31950362

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档