特定子类型不需要工厂 CreateInstance 参数方法

Factory CreateInstance argument method not necessary for a specific subtype

我有一个工厂 class 和 CreateInstance 方法

CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)

工厂可以根据 tipoParametroEntita.TipoCampo.IdTipoCampo

的值实例化两个不同的子类型

重点是 CreateInstance (parametroEntitaMultiValoreDataSourceProvider) 的第二个参数仅用于创建 TipoEntitaTipoParametroEntitaMultiValore
的实例 while 不用于创建 TipoEntitaTipoParametroEntitaSingoloValore

的实例
public class TipoEntitaTipoParametroEntitaFactory : ITipoEntitaTipoParametroEntitaFactory
{
    /// <summary>
    /// Creates an instance of TipoEntitaTipoParametroEntitaSingoloValore or  TipoEntitaTipoParametroEntitaMultiValore 
    /// </summary>
    public TipoEntitaTipoParametroEntita CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)
    {
        if (tipoParametroEntita.TipoCampo.IdTipoCampo == (int)EntityModel.Enum.TipoCampo.CampoLibero ||
            tipoParametroEntita.TipoCampo.IdTipoCampo == (int)EntityModel.Enum.TipoCampo.CampoLiberoMultiLinea)
        {
            return new TipoEntitaTipoParametroEntitaSingoloValore(tipoParametroEntita);
        }

        if (tipoParametroEntita.TipoCampo.IdTipoCampo ==
            (int)EntityModel.Enum.TipoCampo.DropdownListQueryDataSource ||
            tipoParametroEntita.TipoCampo.IdTipoCampo ==
            (int)EntityModel.Enum.TipoCampo.DropdownListTableDataSource)
        {
            return new TipoEntitaTipoParametroEntitaMultiValore(tipoParametroEntita,
                parametroEntitaMultiValoreDataSourceProvider);
        }

        return null;

    }
}

我对这种采用的模式表示怀疑,因为我总是需要传递 IParametroEntitaMultiValoreDataSourceProvider 的实例,即使没有必要,而且阅读该方法签名的人可能会认为创建任何类型的 TipoEntitaTipoParametroEntita 都需要 IParametroEntitaMultiValoreDataSourceProvider 的实例。

什么是更好的方法?两个不同的工厂?只有一个工厂和两个 CreateInstance(一个返回 TipoEntitaTipoParametroEntitaSingoloValore,另一个 TipoEntitaTipoParametroEntitaMultiValore)?

在这两种情况下,我应该已经知道要调用哪个工厂或哪个 CreateInstance,所以我应该每次都提前检查 tipoParametroEntita.TipoCampo.IdTipoCampo。但我只想把这个逻辑放在一个地方。

从函数式编程的角度来看,在处理所谓的 "algebraic data types" 即不同的子类型时,我习惯于查看访问者模式。无论如何,我并不总是喜欢这种方法,因为一开始它可能很困难。

因此我只给出基本思路,以便您可以快速决定是否感兴趣。另请注意,此处的目标是编写具有函数签名的代码,以便可以在 compile 时间发现错误,与 runtime 相反。 =22=]

简而言之,class通过利用 C# 语言类型检查功能实现这一目标的合理方法是定义一个新访问者,包括对 CreateInstance 的所有不同覆盖和签名:

public IEntitaTipoParametroEntita CreateInstance(SubType1 subType1) 
{ 
   // ...
}

public IEntitaTipoParametroEntita CreateInstance(SubType2 subType2) 
{
    // ...
}

每个子类型都应该有自己的

IEntitaTipoParametroEntita accept(CreateVisitor visitor) 
{
    visitor.CreateInstance(this);
}

这样您就可以避免 ifswitch 以及类似的容易出错的子类型检查语法,而只需实例化特定的访问者,然后将其传递给要处理的任何子类型。

DB tables

如果子类型之间存在显着的共性,那么将子类型拆分为单独的物理 tables 可能没有什么价值。

因此,就数据库设计而言,“table per hierarchy”(利用类型鉴别器列来保存类型信息)似乎更适合您的示例:它通过对 SQL 模式进行非规范化来启用多态性。要指示 Entity Framework 使用此策略,只需从 DbContext class 派生一个 class,然后添加一个 DBSet 属性 对于超类型,同时不为子类型添加 DBSet 属性。

阅读链接