"Mapper" è un modello di progettazione valido o è una variante del modello "Factory"?


37

Un modello comune che vedo è quello che è noto come Mappermodello (da non confondere con DataMapperqualcos'altro completamente), che prende come argomento una sorta di origine dati "grezza" (ad esempio un ADO.NET DataReadero DataSet) e mappa i campi su proprietà su un oggetto business / dominio. Esempio:

class PersonMapper
{
    public Person Map(DataSet ds)
    {
        Person p = new Person();
        p.FirstName = ds.Tables[0].Rows[0]["FirstName"].ToString();
        // other properties...
        return p;
    }
}

L'idea è il tuo Gateway / DAO / Repository / ecc. chiamerà nel Mapper prima che ritorni, in modo da ottenere un oggetto business ricco rispetto al contenitore di dati sottostante.

Tuttavia, questo sembra essere correlato, se non identico, al modello Factory (nel linguaggio DDD, comunque), che costruisce e restituisce un oggetto dominio. Wikipedia dice questo riguardo: la fabbrica DDD:

Factory: i metodi per la creazione di oggetti di dominio devono essere delegati a un oggetto Factory specializzato in modo tale che le implementazioni alternative possano essere facilmente scambiate.

Da quella citazione l'unica differenza che mi viene in mente è che la Factory in stile DDD potrebbe essere parametrizzata in modo da poter restituire un tipo di oggetto specializzato in caso di necessità (ad es. BusinessCustomer contro ResidentialCustomer) mentre "Mapper" è impostato su una classe specifica e fa solo la traduzione.

Quindi c'è una differenza tra questi due modelli o sono essenzialmente la stessa cosa con nomi diversi?


È diverso da ORM e, in tal caso, dov'è la differenza?
JB King,

Gli ORM gestiscono automaticamente la mappatura per te - questo è più per uno scenario in cui non puoi utilizzare un ORM (o devi scrivere il tuo livello dati / ORM thin)
Wayne Molina,

1
Faccio davvero fatica a vedere come DataMapper sia "qualcos'altro".
pdr,

Forse mi sbaglio: ho pensato che il DataMappermodello permettesse al database di accedere da solo, mentre questo "Mapper" non viene estratto dal database, ma converte un set di risultati di qualche tipo in un oggetto.
Wayne Molina,

martinfowler.com/eaaCatalog/dataMapper.html In un certo senso capisco cosa intendi ma, leggendo l'ultimo paragrafo, è giusto. Guarda il catalogo PEAA. martinfowler.com/eaaCatalog/index.html . Quello che stai descrivendo è certamente un tipo di Mapper e si adatta più da vicino a DataMapper rispetto al resto.
pdr,

Risposte:


23

Anche se questa è la prima volta che sento parlare del pattern Mapper, per me suona più come il pattern Builder piuttosto che la Factory.

Nel modello Factory incapsuli la logica per la creazione di oggetti di un numero di classi correlate. L'esempio principale sarebbe una situazione in cui è necessario creare un oggetto di una sottoclasse particolare di una classe base astratta a seconda di alcuni parametri. Quindi una Factory restituisce sempre un puntatore o un riferimento alla classe base, ma in realtà crea un oggetto della classe derivata appropriata in base ai parametri forniti.

Al contrario, una classe Builder crea sempre oggetti della stessa classe. Lo useresti se la creazione di un oggetto è complicata, ad esempio il suo costruttore accetta molti argomenti, e non tutti possono essere immediatamente disponibili. Quindi un oggetto builder potrebbe essere un luogo che memorizza i valori per gli argomenti del costruttore fino a quando non li hai tutti e sei pronto a creare il "prodotto", oppure può fornire valori predefiniti ragionevoli e permetterti di specificare solo gli argomenti di cui hai bisogno modificare. Un tipico caso d'uso per il modello Builder è la creazione di oggetti che potrebbero essere necessari in un unit test, per evitare di ingombrare il codice di test con tutta la logica di creazione.

Per me un Mapper suona come una variante di un Builder, in cui i parametri del costruttore si presentano sotto forma di un record di database o di qualche altra struttura di dati "grezzi".


Hmm avevo sentito parlare di Builder ma non ero al 100% consapevole di ciò che comportava - questo ha aiutato a chiarire le cose! Sembra quasi che la differenza principale sia che Factory restituisce un'interfaccia / classe astratta che è davvero una classe concreta basata su parametri (se ciò ha senso) mentre un Builder / Mapper prende i dati effettivi e li associa alle proprietà, senza molta logica (se presente) ?
Wayne Molina,

1
@Waine M: praticamente. Sebbene ci possa essere molta logica in un Builder, perché la mappatura dei dati sulle proprietà potrebbe non essere affatto diretta. In effetti, un builder può contenere altri builder per costruire i parametri. :)
Dima,

5
Il modello Builder consente di inserire nel tempo tutte le informazioni necessarie per creare un oggetto complesso (di solito immutabile) e quindi creare un'istanza dell'oggetto alla fine del processo. Non è quello che sta succedendo qui.
pdr,

+1 Ha convenuto che si tratta di un approccio sensato, che ha una classe 'mapper' separata per fungere da mediatore tra oggetti DTO e oggetti modello di dominio. È inoltre utile quando gli oggetti del modello di dominio devono essere messi in uno stato speciale durante la costruzione (ad es. Interfaccia ISupportInitialize .NET).
MattDavey,

@pdr, sono d'accordo che un Mapper non è esattamente come un builder, perché tutti i dati sono disponibili contemporaneamente. Ma è molto simile, perché costruisce solo un tipo di oggetti.
Dima,

8

L'unica cosa comune su Mapper, Builder e Factory è che forniscono un "prodotto costruito" - e un'istanza di oggetto di un tipo. Per evitare qualsiasi confusione, mi riferisco alle seguenti discussioni per la loro rispettiva definizione.

  1. Mapper: vicino a ciò che è spiegato qui: http://www.codeproject.com/KB/library/AutoMapper.aspx . Questo non è esattamente lo stesso di cui sopra - ma il più vicino che ho trovato su Mapper.

  2. Builder - come definito qui: http://www.oodesign.com/builder-pattern.html

  3. Factory: è definito qui: http://www.oodesign.com/factory-pattern.html

Il mapper è essenzialmente un costruttore al rovescio. Supponiamo per un po ', se non hai un mapper - Quando hai comunque bisogno di molti set di parametri, sono tutti argomenti sul costruttore. Ora che le cose si evolvono, alcune applicazioni non sono a conoscenza di attributi aggiuntivi che devono andare sotto il costruttore dove uno lo calcola o usa il default. La cosa fondamentale è che il mapper può fare questo per te - e sarebbe più utile se questo avesse un collegamento con oggetti esterni per decidere un tale algoritmo per la costruzione.

Il generatore è molto diverso dal mapper. Un builder è essenziale quando un oggetto completo è composto usando molte parti dell'oggetto. È una specie di assemblaggio degli oggetti mettendo insieme molte parti. Anche l'inizializzazione dei singoli oggetti parte è correlata all'esistenza di altre parti.

I modelli di fabbrica sembrano molto semplici all'inizio. Restituisce oggetti di nuova costruzione. Se qualche normale costruttore può darmi un'istanza pienamente funzionale usando un operatore come new ()? perché avrei bisogno di una fabbrica che mi dia gli stessi risultati?

Tuttavia, l'utilizzo del modello di fabbrica è in genere molto specifico; sebbene il più delle volte, non visualizzato in letteratura dove questo è applicato. Di solito, un'applicazione crea una factory condivisa con vari oggetti che devono creare tali oggetti prodotto durante l'esecuzione. Quando vengono creati molti di questi prodotti, il metodo Factory consente la creazione di oggetti in base a determinati criteri, ad esempio, è possibile forzare un determinato modello utilizzato dal metodo factory quando vengono creati tutti gli oggetti. Questo non è né come un metodo di costruzione; qui il prodotto è solo uno (e indipendente). Anche questo non è come mapper; qui set di dati esterni per creare oggetti secondo il client è in realtà minimo. Il modello di fabbrica fornisce davvero (come suggerisce il nome) un oggetto prodotto costantemente simile!

Dipan.



4

Mentre guardo le risposte, vedo tutti gli intervistati fornire risposte semanticamente errate. Penso che questo sia perché sei troppo concentrato sulla domanda, che è focalizzata sul modo in cui il mapper è correlato alla fabbrica o al costruttore.

Quando in realtà Mapper NON è simile a factory o builder. Mapper è più simile al modello dell'adattatore (usando il linguaggio GoF). Il modello di adattatore offre funzionalità per convertire una rappresentazione in un'altra. L'OP si riferiva al DataSet e al DataReader in ADO.NET - e che dire di SqlDataAdapter? La risposta è nel nome. Mapper è un nuovo nome per qualcosa che i programmatori più anziani conoscono da molto tempo: adattatori.

Mapper converte una rappresentazione in un'altra: la definizione stessa del modello di adattatore.


1

Quello che stai facendo qui è in realtà una sorta di conversione del tipo (converti i tuoi dati grezzi in un oggetto business). Puoi usare lo schema di fabbrica per fare esattamente questo (cioè, digitare conversioni), quindi sì, in qualche modo, la tua classe è una fabbrica (anche se per quella userei una Fabbrica statica ).


0

I costruttori incapsulano complesse logiche aziendali per costruire un oggetto. Mapper d'altra parte dovrebbe semplicemente copiare i campi da uno all'altro.

Ad esempio, mappa dall'oggetto Dipendente database all'oggetto Dipendente dominio, mappa dall'oggetto Dipendente dominio al contratto cliente.

I costruttori invece ospitano più decisioni aziendali per costruire un oggetto. Dal punto di vista della responsabilità singola, questo ha senso.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.