Factory CreateInstance argument method not needed for specific subtype

I have a factory class and CreateInstance method

CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider) 

factory can create two different subtypes depending on the value of tipoParametroEntita.TipoCampo.IdTipoCampo

Point - the second argument to CreateInstance ( parametroEntitaMultiValoreDataSourceProvider ) is used only to create an instance of TipoEntitaTipoParametroEntitaMultiValore
whereas not used when instantiating 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; } } 

I doubt this accepted pattern, because I always need to pass an instance of IParametroEntitaMultiValoreDataSourceProvider , even if it is not necessary, and besides, someone reading the signature of the method may make you think that to create any type of TipoEntitaTipoParametroEntita need an instance of IParametroEntitaMultiValoreDataSourceProvider

What would be better? Two great factories? Only one factory and two CreateInstance (one returns TipoEntitaTipoParametroEntitaSingoloValore and the other TipoEntitaTipoParametroEntitaMultiValore )?

In both cases, I should already know which factory or which CreateInstance to call, so I have to check tipoParametroEntita.TipoCampo.IdTipoCampo every time in advance. But I would like to keep this logic in only one place.

+7
c # design-patterns architecture factory-pattern
source share
1 answer

From the point of view of functional programming, I use to see the Visitor template when working with the so-called "algebraic data types", that is, different subtypes. In any case, I'm not always a fan of this approach, as it can be difficult in the beginning.

Therefore, I will give only the basic idea so that you can quickly decide if you are interested. Also note that the goal here is to write code with function signatures so that errors can be accurate at compile time, as opposed to run-time.

Now in a nutshell, the classic way to achieve this, using the C # language type check function, is to define a new visitor, including all the various redefinitions of your CreateInstance with signatures:

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

where each subtype must have its own

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

Thus, you can avoid if and switch and similar syntaxes for checking subtypes that are error prone, and simply create an instance of a specific visitor and simply pass it to any subtype that will be processed.

DB Tables

If there is significant commonality between the subtypes, then the division of the subtypes into separate physical tables is probably of little significance.

Therefore, with regard to database design, the “table by hierarchy” (which uses the type discriminator column to store type information) seems to be better suited to your example: it allows polymorphism by denormalizing the SQL schema. To instruct the Entity Framework to use this strategy, all that is required is to get the class from the DbContext class and add the DBSet property for the supertype without adding the DBSet property for the subtypes.

Reading links

+2
source share

All Articles