Existe um padrão de design para manipular quando o código depende do subtipo de dois objetos
Tentarei ser o mais explícito possível, caso haja uma solução melhor para o meu problema do que responder à minha pergunta.
Estou trabalhando em c #.
Eu tenho um modelo de relatório que pode incluir qualquer número de 'recursos' ativados. Um recurso pode ser uma tabela de informações, um gráfico de barras / torta, uma lista etc. Estou gerando o relatório como um arquivo de texto ou um PDF (possivelmente outras opções no futuro).
Até agora eu tenho umIFeature
interface e alguns tipos de recursos que a implementam:ChartFeature
, ListFeature
, etc. Li a lista de recursos ativados no banco de dados e passo cada um para um método junto com o ID de dados e o método retorna um preenchidoIFeature
do tipo apropriado.
Eu também tenho umIReportWriter
interface queTextReportWriter
e PdfReportWriter implementar. Essa interface possui um método:AddFeature(IFeature)
.
O problema é queAddFeature
em cada escritor acaba parecendo:
public void AddFeature(IFeature)
{
InsertSectionBreakIfNeeded();
if(IFeature is TableFeature)
{
TableFeature tf = (TableFeature)feature;
streamWriter.WriteLine(tf.Title);
for(int row=0; row < tf.Data.First.Length; row++)
{
for(int column=0; i < tf.Data.Length; i++)
{
if(i != 0)
{
streamWriter.Write("|");
}
streamWriter.Write(feature.Data[column][row]);
}
}
}
else if(IFeature is ListFeature)
{
ListFeature lf = (ListFeature)feature;
streamWriter.Write(lf.Title + ": ");
bool first = true;
foreach(var v in lf.Data)
{
if(!first)
{
streamWriter.Write(", ");
}
else
{
first = false;
}
streamWriter.Write(v);
}
}
...
else
{
throw new NotImplementedException();
}
sectionBreakNeeded = true;
}
No gravador de PDF, o acima seria modificado para gerar células de tabela em PDF, caixas de texto e assim por diante.
Isso parece feio. Eu gosto um pouco melhor comoAddFeature(ListFeature){...}
, AddFeature(ChartFeature)
porque pelo menos o tempo de compilação é verificado, mas, na prática, apenas move o problema agora para fora se o IReportWriter que estou chamandoif(feature is ...)
.
Mover o código de exibição para o recurso apenas inverte o problema, pois seria necessário saber se ele deveria escrever texto sem formatação ou PDF.
Alguma sugestão, ou estou melhor apenas usando o que tenho e ignorando meus sentimentos?
Edit: Preenchido algumas das condições para dar às pessoas uma idéia melhor do que está acontecendo. Não se preocupe muito com o código exato desses exemplos; acabei de escrever isso em cima da minha cabeça.