工厂方法模式是否可以使用不同的重载

时间:2016-04-22 07:01:45

标签: c# design-patterns factory-method

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

我在想像

这样的东西
class CarFactory
{
  public ModelS TeslaMaker (List<Battery> batteries){/*return ModelS*/}
  public Mustang FordMaker (Engine engine) {/*return a Mustang*/}
}

而不是说

    class CarFactory
    {
      public Car GetCar(CarType carType) //where CarType is an enum (Ford=0,Tesla=1)
      { 
        switch(carType) 
        {  case CarType.Ford: return new Mustang(); }//just an example
      }
    }

修改: 在我的情况下,我实际上需要返回一个类的家庭。因此,如果它是特斯拉,则返回ModelS,ModelSService,ModelSWarranty等。因此,我将采用抽象工厂方法,该方法将包含此处给出的建议。

4 个答案:

答案 0 :(得分:4)

  

那么,在这种情况下,使用不同签名的多个方法是否有意义,或者根本不是工厂模式?

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

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

目前的方法有一些可能的方法。

一种选择是具有表示构造函数参数的类层次结构。您甚至不需要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 );
        ...

另一个选择是考虑你是否真的需要使用外部引擎(聚合)创建你的Fords,或者更确切地说他们拥有他们的引擎(组合)。在后一种情况下,您可以将无参数构造函数暴露给您的特定汽车类型:

public class Ford : Car
{
     public Engine engine;

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

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

答案 1 :(得分:2)

不,这不是因素模式的一个很好的例子。相反,如果您的Car类依赖于不同类型的组件,那么您也可以为这些组件创建工厂。 E.G对于汽车和发动机,你可以这样:

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

答案 2 :(得分:2)

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

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 CarFactory
    {
          public Car GetCar(CarDetail carDetail) //where CarDetails                  encapsulates all the possible car details
          { 
                 switch(carDetail.type) 
                 {  case CarType.Ford: return new Mustang(carDetail.Engine);//just an example
                 }
          }
    }
    

答案 3 :(得分:0)

是的,这是工厂模式。 工厂模式说创建Object的工厂,但让子类决定实例化对象的方式。 在您根据Enum类型决定

的情况下,情况确实如此