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