Um padrão comum que vejo é o que é conhecido como Mapper
padrão (que não deve ser confundido com o DataMapper
que é algo totalmente diferente), que usa como argumento algum tipo de fonte de dados "bruta" (por exemplo, um ADO.NET DataReader
ou DataSet
) e mapeia os campos para propriedades em um objeto de negócios / domínio. Exemplo:
class PersonMapper
{
public Person Map(DataSet ds)
{
Person p = new Person();
p.FirstName = ds.Tables[0].Rows[0]["FirstName"].ToString();
// other properties...
return p;
}
}
A ideia é o seu Gateway / DAO / Repositório / etc. chamará o Mapper antes de retornar, para que você obtenha um objeto de negócios rico versus o contêiner de dados subjacente.
No entanto, isso parece estar relacionado, se não idêntico, ao padrão Factory (na linguagem DDD, de qualquer maneira), que constrói e retorna um objeto de domínio. A Wikipedia diz o seguinte: a fábrica DDD:
Factory: os métodos para criar objetos de domínio devem delegar para um objeto Factory especializado, de modo que implementações alternativas possam ser facilmente trocadas.
A partir dessa citação, a única diferença que pude pensar é que a Fábrica no estilo DDD pode ser parametrizada para retornar um tipo especializado de objeto, se surgir a necessidade (por exemplo, BusinessCustomer versus ResidentialCustomer) enquanto o "Mapper" estiver ligado a uma classe específica e apenas faz tradução.
Então, existe uma diferença entre esses dois padrões ou eles são essencialmente a mesma coisa com nomes diferentes?
fonte
DataMapper
padrão acessou o banco de dados, enquanto esse "Mapper" não é extraído do banco de dados, apenas converte um conjunto de resultados de algum tipo em um objeto.Respostas:
Embora seja a primeira vez que ouço o padrão Mapper, para mim, parece mais o padrão Builder do que o Factory.
No padrão de fábrica, você encapsula a lógica para criar objetos de várias classes relacionadas. O exemplo principal seria uma situação em que você precisa criar um objeto de uma subclasse específica de alguma classe base abstrata, dependendo de alguns parâmetros. Portanto, um Factory sempre retorna um ponteiro ou uma referência à classe base, mas na verdade cria um objeto da classe derivada apropriada com base nos parâmetros que você fornece.
Por outro lado, uma classe Builder sempre cria objetos da mesma classe. Você o usaria se a criação de um objeto fosse complicada, por exemplo, seu construtor usa muitos argumentos, nem todos disponíveis instantaneamente. Portanto, um objeto construtor pode ser um local que armazena os valores para os argumentos do construtor até você ter todos eles e estar pronto para criar o "produto", ou pode fornecer valores padrão razoáveis e permitir especificar apenas os argumentos cujos valores você precisa mudança. Um caso de uso típico para o padrão Builder é para criar objetos que você pode precisar em um teste de unidade, para evitar sobrecarregar o código de teste com toda a lógica de criação.
Para mim, um mapeador soa como uma variante de um construtor, onde os parâmetros do construtor vêm na forma de um registro de banco de dados ou alguma outra estrutura de dados "bruta".
fonte
A única coisa comum sobre o Mapper, Builder e Factory é que eles entregam um "produto construído" - e uma instância de objeto de um tipo. Para evitar qualquer confusão, refiro-me às discussões a seguir para sua respectiva definição.
Mapeador - próximo ao explicado aqui: http://www.codeproject.com/KB/library/AutoMapper.aspx . Isso não é exatamente o mesmo que acima - mas o mais próximo que encontrei sobre o mapper.
Construtor - conforme definido aqui: http://www.oodesign.com/builder-pattern.html
Fábrica - é definida aqui: http://www.oodesign.com/factory-pattern.html
O mapeador é essencialmente um construtor de dentro para fora. Suponha por um tempo, se você não tiver um mapeador - quando você precisar de muitos conjuntos de parâmetros, todos serão argumentos no construtor. Agora, à medida que as coisas evoluem, alguns aplicativos não estão cientes de atributos adicionais que precisam ser construídos no local em que alguém o calcula ou usa o padrão. O ponto crítico é que o mapeador pode fazer isso por você - e seria mais útil se isso tivesse ligação com objetos externos para decidir esse algoritmo para construção.
O Builder é muito diferente do mapeador. Um construtor é essencial quando um objeto completo é composto usando várias partes do objeto. É como montar os objetos, encaixando muitas partes. Até a inicialização dos objetos individuais da parte está relacionada à existência de outras partes.
Os padrões de fábrica parecem muito simples desde o início. Retorna objetos recém-construídos. Se algum construtor comum puder me fornecer uma instância totalmente funcional usando um operador como new ()? por que eu precisaria de uma fábrica que me desse os mesmos resultados?
No entanto, o uso do padrão de fábrica é geralmente muito específico; embora na maioria das vezes, não seja exibido na literatura onde isso é aplicado. Geralmente, um aplicativo cria uma fábrica que é compartilhada com vários objetos que precisam criar esses objetos de produto durante a execução. Quando muitos desses produtos são criados, o método Factory permite a criação de objetos com base em determinadas políticas, por exemplo, é possível forçar um determinado modelo que é usado pelo método factory quando todos os objetos são criados. Isso não é como um método construtor; aqui o produto fora é apenas um (e independente). Isso também não é como o mapeador; aqui, o conjunto de dados externos para criar objetos de acordo com o cliente é realmente mínimo. O padrão de fábrica realmente fornece (como o nome sugere) objetos de produto consistentemente semelhantes!
Dipan.
fonte
a resposta para sua pergunta: “Mapper” é um padrão de design válido? é sim. Padrão do mapeador, também conhecido como Padrão do Tradutor e é um padrão documentado: http://www.iro.umontreal.ca/~keller/Layla/translator.pdf
fonte
Ao examinar as respostas, vejo todos os respondentes fornecendo respostas semanticamente incorretas. Eu acho que isso ocorre porque você está muito focado na questão, que está focada em como o mapeador está relacionado à fábrica ou construtor.
Quando, de fato, o Mapper NÃO é semelhante à fábrica ou construtor. O Mapper é mais parecido com o padrão do adaptador (usando a linguagem GoF). O padrão do adaptador fornece funcionalidade para converter uma representação em outra. O OP se referiu ao DataSet e ao DataReader no ADO.NET - e quanto ao SqlDataAdapter? A resposta está no nome. Mapper é um novo nome para algo que os programadores mais antigos conhecem há muito tempo: adaptadores.
O Mapper converte uma representação em outra - a própria definição do padrão do adaptador.
fonte
O que você está fazendo aqui é na verdade algum tipo de conversão de tipo (você converte seus dados brutos em um objeto de negócios). Você pode usar o padrão de fábrica para fazer exatamente isso (ou seja, conversões de tipo), então sim, de alguma forma, sua classe é uma fábrica (embora eu usaria uma fábrica estática para isso).
fonte
Os construtores encapsulam uma lógica de negócios complexa para construir um objeto. Por outro lado, o mapeador deve copiar os campos de um para o outro.
Por exemplo, mapear do objeto Employee do banco de dados para o objeto Employee do domínio, mapear do objeto Employee do domínio para o contrato do cliente.
Os construtores, por outro lado, hospedam várias decisões de negócios para construir um objeto. Do ponto de vista de responsabilidade única, isso faz sentido.
fonte