C# 对接受不同数量参数的派生类使用工厂模式
我正在使用下面的 我可能需要为所有派生类传入参数,不管它们是否使用:C# 对接受不同数量参数的派生类使用工厂模式,c#,.net,visual-studio,design-patterns,factory-pattern,C#,.net,Visual Studio,Design Patterns,Factory Pattern,我正在使用下面的 我可能需要为所有派生类传入参数,不管它们是否使用: var position = Factory.Get(i, param1, param2, param3); 需要修改switch语句: public static Position Get(int id, param1, param2, param3) //HERE IS THE MODIFIED PARAM LIST { switch (id) { case 0: return n
var position = Factory.Get(i, param1, param2, param3);
需要修改switch语句:
public static Position Get(int id, param1, param2, param3) //HERE IS THE MODIFIED PARAM LIST
{
switch (id)
{
case 0:
return new Manager(param1); //MODIFIED
case 1:
case 2:
return new Clerk(param2, param3); //MODIFIED
case 3:
default:
return new Programmer(param3); //MODIFIED
}
}
我对factory模式所做的修改是否破坏了该模式,我是否应该使用不同的模式来创建对象?该示例有点过于简单,但是的,您可以 也就是说,这个例子可能会导致一些问题,因为程序员可能会对如何使用工厂感到困惑。例如,假设您必须定义一个GUI来创建位置:GUI是否要求用户提供所有3个
param
值,即使它们对最初定义的位置没有意义?如果你回答“是”,用户会感到困惑,如果你回答“否”,那么工厂就不是一个黑箱
我使用这种方法的一个例子是计费;我的应用程序批量向许多人支付了当月的服务费用。有些人按月份的自然天数收费,有些人按劳动天数收费。由于获取劳动日的速度有点慢(必须在当地和国家节假日咨询DB),我将其缓存并将其传递给需要它的实例
它有点像(Java):
公共类BillerFactory{
私有HashMap holidayCache=
新的HashMap();
...
公共getBiller(BillingType BillingType,日期为每月第一个){
开关(billingType){
case BillingType.NATURAL:
返回新的自然填充器(第一个月);
案例BillingType.LABORAL:
ListOfHoliday假日=this.holidayCache.get(月初);
如果(假日==null){
假日=此。计算假日(月初);
holidayCache.put(月初,节假日);
}
归还新的劳工(月初,节假日);
}
}
TLDR:问题不在于构造器有不同的参数,而在于在您的示例中,您强制客户机提供可能没有意义的数据。该示例有点过于简化,但是的,您可以 也就是说,这个例子可能会导致一些问题,因为程序员可能会对如何使用工厂感到困惑。例如,假设您必须定义一个GUI来创建位置:GUI是否会要求用户提供所有3个
param
值,即使它们对最初定义的位置没有意义?如果您回答“是”用户会感到困惑,如果你回答“否”,那么工厂就不是一个黑箱
我使用这种方法的一个例子是计费;我的应用程序将同一个月的服务批量计费给许多人。有些人按当月的自然天数计费,有些人按可工作天数计费。因为获得可工作天数有点慢(它必须就当地和国家节假日咨询DB)我缓存了它,并将其传递给需要它的实例
它有点像(Java):
公共类BillerFactory{
私有HashMap holidayCache=
新的HashMap();
...
公共getBiller(BillingType BillingType,日期为每月第一个){
开关(billingType){
case BillingType.NATURAL:
返回新的自然填充器(第一个月);
案例BillingType.LABORAL:
ListOfHoliday假日=this.holidayCache.get(月初);
如果(假日==null){
假日=此。计算假日(月初);
holidayCache.put(月初,节假日);
}
归还新的劳工(月初,节假日);
}
}
TLDR:问题不在于构造函数有不同的参数,而在于在您的示例中,您强制客户机提供可能没有意义的数据。下面的代码将在Position类中使用默认构造函数
static void Main(字符串[]args)
{
经理mngr=新经理();
}
}
公共抽象类位置
{
公共抽象字符串标题{get;}
公共职位()
{
}
}
公共课经理:职位
{
公共重写字符串标题
{
得到
{
返回“经理”;
}
}
}
下面的代码将在Position类中使用默认构造函数
static void Main(字符串[]args)
{
经理mngr=新经理();
}
}
公共抽象类位置
{
公共抽象字符串标题{get;}
公共职位()
{
}
}
公共课经理:职位
{
公共重写字符串标题
{
得到
{
返回“经理”;
}
}
}
对于我来说,没有足够的上下文来建议一个好的替代方案,但是您的示例使用起来并不舒服:工厂模式的想法是封装对象的创建,但是由于您对不同的对象有不同的参数集,您必须知道具体实现之间的一些差异,或者您必须提供无用的数据每次都是ata。也许只使用构造函数更好?我没有足够的上下文来建议一个好的替代方案,但您的示例使用起来并不舒服:工厂模式的想法是封装对象的创建,但由于您对不同的对象有不同的参数集,您必须知道c和c之间的一些差异oncrete实现,或者每次都必须提供无用的数据。也许使用构造函数更好?工厂的用途是抽象如何创建对象的需求,以便允许
var position = Factory.Get(i);
var position = Factory.Get(i, param1, param2, param3);
public static Position Get(int id, param1, param2, param3) //HERE IS THE MODIFIED PARAM LIST
{
switch (id)
{
case 0:
return new Manager(param1); //MODIFIED
case 1:
case 2:
return new Clerk(param2, param3); //MODIFIED
case 3:
default:
return new Programmer(param3); //MODIFIED
}
}
public class BillerFactory {
private HashMap<Date, ListOfHolidaysInMonth> holidayCache =
new HashMap<>();
...
public getBiller(BillingType billingType, Date firstOfMonth) {
switch (billingType) {
case BillingType.NATURAL:
return new NaturalBiller(firstOfMonth);
case BillingType.LABORAL:
ListOfHoliday holidays = this.holidayCache.get(firstOfMonth);
if (holidays == null) {
holidays = this.calculateHolidays(firstOfMonth);
holidayCache.put(firstOfMonth, holidays);
}
return new LaboralBiller(firstOfMonth, holidays);
}
}
abstract class Position
{
public abstract string Title { get; }
}
class Manager : Position
{
public Manager(string department) { }
public override string Title => "Manager";
}
class Clerk : Position
{
public override string Title => "Clerk";
}
class Programmer : Position
{
public Programmer(string language) { }
public override string Title => "Programmer";
}
static class Factory
{
private static Dictionary<int, Func<Position>> _registry =
new Dictionary<int, Func<Position>>();
public static void Register(int id, Func<Position> factory)
{
_registry[id] = factory;
}
public static Position Get(int id)
{
return _registry[id].Invoke();
}
}
Factory.Register(1, () => new Manager("Sales"));
Factory.Register(2, () => new Clerk());
Factory.Register(3, () => new Programmer("C#"));
var position = Factory.Get(3);