Neste exemplo, resolvemos novamente o exercício proposto para a atividade de reflection, sem usar esse recurso.
O problema que queremos resolver é: Como fazer com que a tabela possa imprimir os dados de qualquer classe, sem que precisemos alterar a implementação da classe que ela imprime?
A solução para isso está no padrão Data Mapper. Neste padrão criamos uma interface que encapsula o acesso aos dados (DataSource). A tabela então consulta essa interface na hora de se desenhar.
Nesta implementação, a interface foi chamada de TableDatasource e define métodos para informar a tabela a quantidade de linhas, colunas, cabeçalhos, valores e formatos de dado. Enquanto a classe Table continua encarregada pelo desenho da tabela em si.
Foram feitas duas implementações diferentes dessa interface. A DogDatasource, mais simples e direta, porém com o mau cheiro de ter vários switchs. E a PlanetDatasource que resolve o mal cheiro criando um enum de colunas.
Observe que o resultado final, ao executar o main é exatamente o mesmo do projeto com reflection.