【问题标题】:Factory CreateInstance argument method not necessary for a specific subtype特定子类型不需要工厂 CreateInstance 参数方法
【发布时间】:2017-04-29 21:06:27
【问题描述】:

我有一个工厂类和 CreateInstance 方法

CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)

工厂可以根据tipoParametroEntita.TipoCampo.IdTipoCampo的值实例化两种不同的子类型

重点是CreateInstance的第二个参数(parametroEntitaMultiValoreDataSourceProvider)仅用于创建TipoEntitaTipoParametroEntitaMultiValore的实例
而不是用于创建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 的实例,即使没有必要,而且阅读该方法签名的人可能会认为创建任何类型的 @ 987654330@ 需要IParametroEntitaMultiValoreDataSourceProvider 的实例。

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

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

【问题讨论】:

标签: c# .net design-patterns architecture factory-pattern


【解决方案1】:

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

因此,我只给出基本的想法,以便您可以快速决定是否感兴趣。另请注意,这里的目标是编写带有函数签名的代码,以便可以在编译时发现错误,这与运行时相反。

现在简而言之,通过利用 C# 语言类型检查功能来实现这一点的经典方法是定义一个新访问者,包括带有签名的 CreateInstance 的所有不同覆盖:

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

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

每个子类型应该有自己的

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

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

数据库表

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

因此,就 DB 设计而言,“table per hierarchy”(它利用类型鉴别器列来保存类型信息)似乎更适合您的示例:它通过对SQL 架构。要指示 Entity Framework 使用此策略,只需从 DbContext 类派生一个类,并为超类型添加 DBSet 属性,而不为子类型添加 DBSet 属性。

阅读链接

【讨论】:

  • 感谢您的努力,您让我有机会了解我以前从未深入研究过的访问者模式。这里的重点是我没有 EntityModel.TipoEntitaTipoParametroEntita 的子类型,这意味着我没有 subType1 和 subType2 .....
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多