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