Typowy wzorzec, który widzę, to tak zwany Mapper
wzorzec (którego nie należy mylić z DataMapper
czymś zupełnie innym), który jako argument przyjmuje pewne „surowe” źródło danych (np. ADO.NET DataReader
lub DataSet
) i mapuje pola na właściwości obiektu biznesowego / domeny. Przykład:
class PersonMapper
{
public Person Map(DataSet ds)
{
Person p = new Person();
p.FirstName = ds.Tables[0].Rows[0]["FirstName"].ToString();
// other properties...
return p;
}
}
Ideą jest twoja brama / DAO / Repository / etc. zadzwoni do programu mapującego przed jego zwróceniem, aby uzyskać bogaty obiekt biznesowy w porównaniu do bazowego kontenera danych.
Wydaje się jednak, że jest to powiązane, jeśli nie identyczne, ze wzorem Factory (w każdym razie w języku DDD), który konstruuje i zwraca obiekt domeny. Wikipedia mówi, że to: Fabryka DDD:
Fabryka: metody tworzenia obiektów domeny powinny być przekazywane do wyspecjalizowanego obiektu fabryki, tak aby alternatywne implementacje mogły być łatwo wymieniane.
Z tego cytatu jedyną różnicą, o której mogłem pomyśleć, jest to, że Fabrykę w stylu DDD można sparametryzować, aby mogła zwrócić specjalistyczny typ obiektu, jeśli zajdzie taka potrzeba (np. BusinessCustomer kontra ResidentialCustomer), podczas gdy „Mapper” jest przypisany do konkretnej klasy i tylko tłumaczenie.
Czy istnieje różnica między tymi dwoma wzorami, czy są one zasadniczo takie same z różnymi nazwami?
źródło
DataMapper
wzorzec sam miał dostęp do bazy danych, podczas gdy ten „Mapper” nie pobiera danych z bazy danych, po prostu konwertuje jakiś zestaw wyników na obiekt.Odpowiedzi:
Chociaż po raz pierwszy słyszę wzór Mappera, dla mnie to bardziej przypomina wzór Buildera niż Factory.
We wzorcu fabrycznym hermetyzujesz logikę tworzenia obiektów szeregu powiązanych klas. Pierwszym przykładem może być sytuacja, w której trzeba utworzyć obiekt określonej podklasy pewnej abstrakcyjnej klasy bazowej w zależności od niektórych parametrów. Tak więc fabryka zawsze zwraca wskaźnik lub referencję do klasy bazowej, ale w rzeczywistości tworzy obiekt odpowiedniej klasy pochodnej na podstawie podanych parametrów.
Natomiast klasa Builder zawsze tworzy obiekty tej samej klasy. Użyłbyś go, gdyby utworzenie obiektu było skomplikowane, np. Jego konstruktor przyjmuje wiele argumentów, z których nie wszystkie mogą być dostępne natychmiast. Tak więc obiekt konstruktora może być miejscem, w którym przechowywane są wartości argumentów konstruktora, dopóki nie będziesz mieć ich wszystkich i nie będziesz gotowy do utworzenia „produktu”, lub może dostarczyć rozsądne wartości domyślne i pozwolić ci tylko określić argumenty, których wartości potrzebujesz zmiana. Typowym przypadkiem użycia wzorca konstruktora jest tworzenie obiektów, które mogą być potrzebne w teście jednostkowym, aby uniknąć zaśmiecania kodu testowego całą logiką tworzenia.
Dla mnie Mapper brzmi jak wariant Konstruktora, w którym parametry konstruktora mają postać rekordu bazy danych lub innej „surowej” struktury danych.
źródło
Jedyną powszechną rzeczą w Mapper, Builder i Factory jest to, że dostarczają one „skonstruowany produkt” - i obiektową instancję typu. Aby uniknąć nieporozumień, odnoszę się do poniższych dyskusji dotyczących ich odpowiedniej definicji.
Mapper - zbliżony do wyjaśnienia tutaj: http://www.codeproject.com/KB/library/AutoMapper.aspx . Nie jest to dokładnie to samo co powyżej - ale najbliższe, jakie znalazłem na temat mapera.
Konstruktor - jak zdefiniowano tutaj: http://www.oodesign.com/builder-pattern.html
Fabryka - jest zdefiniowana tutaj: http://www.oodesign.com/factory-pattern.html
Maper jest zasadniczo konstruktorem wywróconym na lewą stronę. Załóżmy, że przez chwilę, jeśli nie masz mapera - kiedy i tak potrzebujesz wielu zestawów parametrów, wszystkie są argumentami konstruktora. W miarę ewolucji niektóre aplikacje nie są świadome dodatkowych atrybutów, które muszą przejść do konstruktora, w którym albo go oblicza, albo używa domyślnego. Najważniejsze jest to, że program mapujący może to zrobić za Ciebie - i byłoby bardziej użyteczne, gdyby miało to powiązanie z obiektami zewnętrznymi w celu podjęcia decyzji o takim algorytmie konstrukcyjnym.
Konstruktor różni się bardzo od mapera. Konstruktor jest niezbędny, gdy kompletny obiekt składa się z wielu części obiektu. To rodzaj łączenia obiektów przez połączenie wielu części. Nawet inicjalizacja poszczególnych obiektów części związana jest z istnieniem innych części.
Fabryczne wzory na początku wyglądają bardzo prosto. Zwraca nowo zbudowane obiekty. Czy jakikolwiek zwykły konstruktor może dać mi w pełni funkcjonalną instancję za pomocą operatora takiego jak new ()? dlaczego miałbym potrzebować fabryki, która da mi takie same wyniki?
Jednak użycie wzorca fabrycznego jest zazwyczaj bardzo specyficzne; chociaż najczęściej nie są wyświetlane w literaturze, gdzie jest to stosowane. Zwykle aplikacja tworzy fabrykę, która jest udostępniana różnym obiektom, które muszą tworzyć takie obiekty produktu podczas wykonywania. Gdy powstaje wiele takich produktów, metoda Factory pozwala na tworzenie obiektów na podstawie pewnych zasad, na przykład, można wymusić określony szablon, który jest używany przez metodę fabryczną, gdy wszystkie obiekty są tworzone. To nie jest ani metoda budowniczego; tutaj produkt jest tylko jeden (i niezależny). To również nie przypomina mapera; tutaj zewnętrzny zestaw danych do stworzenia obiektu według klienta jest w rzeczywistości minimalny. Wzorzec fabryczny naprawdę zapewnia (jak sama nazwa wskazuje) konsekwentnie podobne obiekty produktu!
Dipan.
źródło
odpowiedź na twoje pytanie: Czy „Mapper” jest prawidłowym wzorcem projektowym? jest tak. Wzorzec mapowania jest również znany jako Wzorzec translatora i jest udokumentowanym wzorcem: http://www.iro.umontreal.ca/~keller/Layla/translator.pdf
źródło
Przeglądając odpowiedzi widzę, że wszyscy respondenci udzielają semantycznie niepoprawnych odpowiedzi. Myślę, że dzieje się tak, ponieważ zbytnio skupiasz się na pytaniu, które koncentruje się na powiązaniu mapera z fabryką lub konstruktorem.
Kiedy w rzeczywistości Mapper NIE jest podobny do fabryki lub konstruktora. Mapper najbardziej przypomina wzorzec adaptera (używając języka GoF). Wzorzec adaptera zapewnia funkcjonalność konwersji jednej reprezentacji na inną. OP odwoływał się do DataSet i DataReader w ADO.NET - a co z SqlDataAdapter? Odpowiedź jest w imieniu. Mapper to nowa nazwa czegoś, o czym od dawna znali się programiści: adaptery.
Mapper konwertuje jedną reprezentację na drugą - samą definicję wzorca adaptera.
źródło
To, co tutaj robisz, to w rzeczywistości pewnego rodzaju konwersja typu (konwertujesz surowe dane na obiekt biznesowy). Możesz użyć Wzorca Fabrycznego do robienia dokładnie tego (tj. Konwersji typów), więc tak, w pewnym sensie, twoja klasa jest fabryką (chociaż do tego użyłbym Statycznej Fabryki ).
źródło
Konstruktorzy obudowują złożoną logikę biznesową, aby zbudować obiekt. Z drugiej strony Mapper powinien po prostu skopiować pola z jednego do drugiego.
Na przykład mapa z obiektu pracownika bazy danych do obiektu pracownika domeny, mapa z obiektu pracownika domeny do umowy z klientem.
Z drugiej strony konstruktorzy podejmują wiele decyzji biznesowych dotyczących budowy obiektu. Z punktu widzenia pojedynczej odpowiedzialności ma to sens.
źródło