C# 工厂方法模式可以使用不同的重载吗

C# 工厂方法模式可以使用不同的重载吗,c#,design-patterns,factory-method,C#,Design Patterns,Factory Method,我有一个用例,需要构建一个工厂类,该类根据所传递的枚举返回不同的具体类型。但是,每种类型都需要不同的构造函数参数。那么,在这种情况下,有多个具有不同签名的方法是有意义的,还是根本不是工厂模式 我在想 class CarFactory { public ModelS TeslaMaker (List<Battery> batteries){/*return ModelS*/} public Mustang FordMaker (Engine engine) {/*return

我有一个用例,需要构建一个工厂类,该类根据所传递的枚举返回不同的具体类型。但是,每种类型都需要不同的构造函数参数。那么,在这种情况下,有多个具有不同签名的方法是有意义的,还是根本不是工厂模式

我在想

class CarFactory
{
  public ModelS TeslaMaker (List<Battery> batteries){/*return ModelS*/}
  public Mustang FordMaker (Engine engine) {/*return a Mustang*/}
}
编辑
在我的例子中,我实际上需要返回一个类族。所以,如果是特斯拉,返回一个模型,一个模型服务,一个模型服务,等等。所以我将使用抽象工厂方法,它将包装这里给出的建议。

是的,这是工厂模式。 工厂模式表示创建对象的工厂,但让子类决定实例化对象的方式。
这在您的情况下是正确的,您根据枚举类型来决定是的,它是工厂模式。 工厂模式表示创建对象的工厂,但让子类决定实例化对象的方式。
这在您的案例中是正确的,您根据枚举类型来决定,这不是一个很好的因子模式示例。相反,如果你的汽车等级取决于不同类型的部件,你也可以为这些部件建立工厂。例如,对于汽车和发动机,您可以选择:

    public interface ICar
    {
        IEngine Engine { get; set; }
    }

    public class Mustang : ICar
    {
        private IEngine _engine = EngineFactory.GetEngine(EngineType.Mustang);
        public IEngine Engine
        {
            get { return _engine; }
            set { _engine = value; }
        }
    } 

    public class CarFactory
    {
        public ICar GetCar(CarType carType)
        {
            switch (carType)
            { case CarType.Ford: return new Mustang(); }
        }
    }
发动机也是如此

    public interface IEngine { }

    public class MustangEngine : IEngine
    {

    }

    public class EngineFactory
    {

        public static IEngine GetEngine(EngineType engine)
        {
            switch (engine)
            { case EngineType.Mustang: return new MustangEngine(); }
        }
    }

不,这不是一个很好的因素模式的例子。相反,如果你的汽车等级取决于不同类型的部件,你也可以为这些部件建立工厂。例如,对于汽车和发动机,您可以选择:

    public interface ICar
    {
        IEngine Engine { get; set; }
    }

    public class Mustang : ICar
    {
        private IEngine _engine = EngineFactory.GetEngine(EngineType.Mustang);
        public IEngine Engine
        {
            get { return _engine; }
            set { _engine = value; }
        }
    } 

    public class CarFactory
    {
        public ICar GetCar(CarType carType)
        {
            switch (carType)
            { case CarType.Ford: return new Mustang(); }
        }
    }
发动机也是如此

    public interface IEngine { }

    public class MustangEngine : IEngine
    {

    }

    public class EngineFactory
    {

        public static IEngine GetEngine(EngineType engine)
        {
            switch (engine)
            { case EngineType.Mustang: return new MustangEngine(); }
        }
    }

如果您需要不同的对象创建参数(特斯拉电池或福特发动机),您可以在不同的解决方案中选择: -在创建工厂时传递所有这些参数-这将是所有类型汽车的特定工厂,具有这些可用的详细信息

class SpecificCarFactory
{
  public SpecificCarFactory(IList<Battery> batteries, IList<Engine> engines)
  {
    //save batteries etc into local  properties
  }
  public Car GetCar(CarType carType)
  { 
    switch(carType) 
    {  case CarType.Ford: return new Mustang(_engines.First()); }
  }
}

如果您需要不同的参数来创建对象(特斯拉电池或福特发动机),您可以在不同的解决方案中进行选择: -在创建工厂时传递所有这些参数-这将是所有类型汽车的特定工厂,具有这些可用的详细信息

class SpecificCarFactory
{
  public SpecificCarFactory(IList<Battery> batteries, IList<Engine> engines)
  {
    //save batteries etc into local  properties
  }
  public Car GetCar(CarType carType)
  { 
    switch(carType) 
    {  case CarType.Ford: return new Mustang(_engines.First()); }
  }
}
那么,在这种情况下,有多个具有不同签名的方法是有意义的,还是根本不是工厂模式

拥有一个有特定方法的工厂是没有任何意义的。如果客户机代码必须决定应该使用哪种特定方法,为什么不直接调用特定car的构造函数呢?在您的示例中,工厂方法仅仅是特定构造函数的包装器

另一方面,通过使用enum调用单个工厂方法,您的客户机有机会动态决定应该创建哪辆车,例如,决策可以基于数据库查询

围绕您当前的方法,有一些可能的方法

一种选择是拥有表示构造函数参数的类的层次结构。您甚至不需要枚举,因为参数类型足以推断应该创建哪个特定的汽车:

public abstract class CarCreationParams { }

public class FordCreationParams : CarCreationParams
{
    public Engine engine;
}

...

public class CarFactory
{
    public Car GetCar( CarCreationParams parms )
    {
        if ( parms is FordCreationParams )
            return new Ford( ((FordCreationParams)parms).engine );
        ...
另一个选择是思考你是否真的需要你的福特车使用外部引擎(聚合)或者他们拥有自己的引擎(组合)。在后一种情况下,您可以将无参数构造函数公开给特定的汽车类型:

public class Ford : Car
{
     public Engine engine;

     // car is composed of multiple parts, including the engine
     public Ford()
     { 
          this.engine = new FordEngine();
     }
这使得工厂的实施更加容易

那么,在这种情况下,有多个具有不同签名的方法是有意义的,还是根本不是工厂模式

拥有一个有特定方法的工厂是没有任何意义的。如果客户机代码必须决定应该使用哪种特定方法,为什么不直接调用特定car的构造函数呢?在您的示例中,工厂方法仅仅是特定构造函数的包装器

另一方面,通过使用enum调用单个工厂方法,您的客户机有机会动态决定应该创建哪辆车,例如,决策可以基于数据库查询

围绕您当前的方法,有一些可能的方法

一种选择是拥有表示构造函数参数的类的层次结构。您甚至不需要枚举,因为参数类型足以推断应该创建哪个特定的汽车:

public abstract class CarCreationParams { }

public class FordCreationParams : CarCreationParams
{
    public Engine engine;
}

...

public class CarFactory
{
    public Car GetCar( CarCreationParams parms )
    {
        if ( parms is FordCreationParams )
            return new Ford( ((FordCreationParams)parms).engine );
        ...
另一个选择是思考你是否真的需要你的福特车使用外部引擎(聚合)或者他们拥有自己的引擎(组合)。在后一种情况下,您可以将无参数构造函数公开给特定的汽车类型:

public class Ford : Car
{
     public Engine engine;

     // car is composed of multiple parts, including the engine
     public Ford()
     { 
          this.engine = new FordEngine();
     }

这使得工厂的实现更加容易。

第一个工厂实际上没有枚举部分。@nyrguds-是的,这就是为什么我怀疑它是否是工厂模式。第一个工厂实际上没有枚举部分。@nyrguds-是的,这就是为什么我怀疑它是否是工厂模式的原因。封装是好的,但由于每种类型都需要不同的参数,所以有一个不应该忘记的步骤:检查定义到传递对象中的参数(如果没有,这只是
NullReferenceException
的神奇配方)当然,这应该通过使用断言或CodeContracts框架来实现。我最初考虑过这一点,但认为当我只需要一部分参数时,传递所有内容都有点混乱。您还需要工厂来提供创建汽车所需的所有资源,并将这些工厂作为依赖项传递进入汽车厂。在这种情况下,工厂方法只需要catType,这是正确的。我正在考虑使用这个建议的一部分,让抽象工厂(工厂的工厂)接收所有参数,然后将一部分参数委托给子工厂。封装是好的,但是由于每种类型需要不同的参数,有一个步骤是不应该忘记的:检查t