Чи "Mapper" є дійсним дизайнерським малюнком чи це варіація "Фабричного" шаблону?


37

Поширений зразок, який я бачу, - це відомий як Mapperшаблон (не плутати з ним DataMapper- це щось інше цілком), який бере в якості аргументу якесь «сире» джерело даних (наприклад, ADO.NET DataReaderабо DataSet) і відображає поля на властивості на об'єкті бізнесу / домену. Приклад:

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

Ідея - ваш шлюз / DAO / сховище / тощо. зателефонує до Mapper, перш ніж він повернеться, тому ви отримаєте багатий бізнес-об'єкт порівняно з базовим контейнером даних.

Однак це, мабуть, пов’язано, якщо не ідентично, з заводською схемою (у будь-якому разі, мова йде про DDD), яка будує та повертає об’єкт домену. Вікіпедія говорить про це: завод DDD:

Фабрика: методи створення об’єктів домену повинні бути делеговані спеціалізованому об'єкту Factory таким чином, що альтернативні реалізації можуть бути легко замінені.

З цієї цитати я міг би думати лише про те, що Фабрика стилю DDD може бути параметризована, щоб вона могла повернути спеціалізований тип об'єкта, якщо виникне потреба (наприклад, BusinessCustomer проти ResidentialCustomer), тоді як "Mapper" введений у певний клас і лише переклад.

Так чи є різниця між цими двома візерунками чи вони по суті одне й те саме з різними назвами?


Чи відрізняється це від ORM і якщо так, то де різниця?
JB King

ORM обробляють відображення автоматично для вас - це більше для сценарію, коли ви не можете використовувати ORM (або потрібно написати власний рівень даних / тонкий ORM)
Wayne Molina

1
Мені дуже важко бачити, як DataMapper - це "щось інше цілком".
pdr

Можливо, я помиляюсь - я вважав, що DataMapperшаблоном був доступ до бази даних сам, тоді як цей «Mapper» не витягує з бази даних, а просто перетворює набір результатів у об’єкт.
Уейн Моліна

martinfowler.com/eaaCatalog/dataMapper.html Я начебто бачу, що ви маєте на увазі, але, читаючи останній абзац, це все правильно. Подивіться каталог PEAA. martinfowler.com/eaaCatalog/index.html . Те, що ви описуєте, це, безумовно, тип Mapper і більше відповідає програмі DataMapper, ніж решта.
pdr

Відповіді:


23

Хоча це вперше я чую про шаблон Mapper, мені це звучить більше як шаблон Builder, а не заводський.

У «Заводському шаблоні» ви інкапсулюєте логіку створення об’єктів із ряду пов’язаних класів. Основним прикладом може бути ситуація, коли вам потрібно створити об’єкт певного підкласу деякого абстрактного базового класу залежно від деяких параметрів. Отже, Factory завжди повертає вказівник або посилання на базовий клас, але він фактично створює об'єкт відповідного похідного класу на основі параметрів, які ви йому надаєте.

На відміну від цього, клас Builder завжди створює об'єкти одного класу. Ви можете використовувати його, якщо створення об'єкта є складним, наприклад, його конструктор бере багато аргументів, не всі з яких можуть бути доступні миттєво. Таким чином, об’єктом builder може бути місце, яке зберігає значення для аргументів конструктора, поки ви не маєте їх усіх і не будете готові створити "продукт", або він може надати розумні значення за замовчуванням і дозволяти вам лише вказати аргументи, значення яких потрібно змінити. Типовий випадок використання для шаблону Builder - це для створення об'єктів, які можуть вам знадобитися в одиничному тесті, щоб уникнути захаращення тестового коду всією логікою створення.

Для мене Mapper звучить як варіант Builder, де параметри конструктора надходять у вигляді запису бази даних або іншої "необробленої" структури даних.


Хм, я чув про Builder, але не знав на 100%, що це спричиняє - це допомогло зрозуміти речі! Це майже звучить як основна різниця: Factory повертає інтерфейс / абстрактний клас, який дійсно є конкретним класом на основі параметрів (якщо це має сенс), тоді як Builder / Mapper приймає фактичні дані та відображає їх у властивості, без особливої ​​логіки (якщо така є) ?
Уейн Моліна

1
@Waine M: досить багато. Хоча в Builder може бути багато логіки, оскільки відображення даних у властивості може зовсім не бути прямим. Фактично, будівельник може містити інших будівельників для побудови параметрів. :)
Діма

5
Шаблон Builder дозволяє помістити всю інформацію, необхідну для складання складного (як правило, незмінного) об'єкта, з часом, а потім інстанціювати об'єкт в кінці процесу. Це не те, що тут відбувається.
pdr

+1 Погодився, що це розумний підхід, який має окремий клас "картограф", який виступає посередником між об'єктами DTO та об'єктами доменної моделі. Це також стане в нагоді, коли об’єкти доменної моделі під час її створення повинні бути переведені в якийсь особливий стан (тобто інтерфейс .NET ISupportInitialize).
MattDavey

@pdr, я погоджуюся, що Mapper не зовсім схожий на будівельника, тому що всі дані доступні одразу. Але він дуже схожий, бо будує лише один тип об’єктів.
Діма

8

Єдине спільне про Mapper, Builder і Factory - це те, що вони доставляють "сконструйований продукт" - і об'єктний примірник типу. Щоб уникнути плутанини, я маю на увазі наступні дискусії для їх відповідного визначення.

  1. Mapper - близько до того, що тут пояснено: http://www.codeproject.com/KB/library/AutoMapper.aspx . Це не точно так само, як вище - але найближче я знайшов про картограф.

  2. Builder - як визначено тут: http://www.oodesign.com/builder-pattern.html

  3. Фабрика - тут визначено: http://www.oodesign.com/factory-pattern.html

Маппер по суті є конструктором зсередини. Припустимо, на деякий час, якщо у вас немає картографа - коли вам все одно потрібно багато параметрів, всі вони є аргументами на конструкторі. Тепер, коли все розвивається, деякі додатки не знають додаткових атрибутів, які потребують переходу в конструктор, де його або обчислюють, або використовують типові. Найважливішим є те, що картограф може зробити це за вас - і було б корисніше, якщо цей зв'язок із зовнішніми об'єктами вирішує такий алгоритм побудови.

Будівельник дуже відрізняється від картографічного. Конструктор є важливим, коли повний об'єкт складається з багатьох частин об'єкта. Це свого роду збірка предметів, з'єднуючи багато деталей. Навіть ініціалізація окремих об'єктів частини пов'язана з існуванням інших частин.

Фабричні візерунки виглядають з самого початку дуже просто. Він повертає щойно побудовані об'єкти. Якщо будь-який звичайний конструктор може надати мені повністю функціональний екземпляр, використовуючи оператора, як new ()? навіщо мені потрібна фабрика, яка дає мені ті ж результати?

Однак використання заводського зразка, як правило, дуже специфічне; хоча найчастіше, не відображається в літературі, де це застосовується. Зазвичай програма створює фабрику, яку поділяють на різні об'єкти, яким необхідно створити такі об’єкти продукту під час виконання. Коли створено багато таких продуктів, метод Factory дозволяє створювати об'єкти, наприклад, за певною політикою , можна створити певний шаблон, який використовується заводським методом при створенні всіх об'єктів. Це не так, як метод будівельника; тут продукт виходить лише один (і незалежний). Це теж не так, як картограф; тут зовнішній набір даних для створення об'єкта за клієнтом насправді мінімальний. Заводський зразок дійсно забезпечує (як випливає з назви) послідовно подібних предметів товару!

Діпан.



4

Переглядаючи відповіді, я бачу, що всі респонденти дають семантично неправильні відповіді. Я думаю, що це тому, що ви занадто зосереджені на питанні, яке зосереджено на тому, як картограф пов’язаний із заводом чи будівельником.

Насправді Mapper НЕ схожий на завод або будівельник. Mapper найбільше нагадує схему адаптера (використовуючи мову GoF). Шаблон адаптера забезпечує функціональність для перетворення одного представлення в інше. ОП посилалося на DataSet та DataReader в ADO.NET-- ну як щодо SqlDataAdapter? Відповідь у назві. Mapper - це нова назва чогось, про що давно знають старші програмісти: адаптери.

Mapper перетворює одне подання в інше - саме визначення схеми адаптера.


1

Що ви тут робите, це насправді якесь перетворення типів (ви перетворюєте свої необроблені дані в бізнес-об’єкт). Ви можете використовувати заводський зразок для того, щоб зробити це дуже точно (тобто, ввести конверсії), так що так, так чи інакше, ваш клас є фабрикою (хоча я б для цього використовував статичну фабрику ).


0

Будівельники інкапсулюють складну бізнес-логіку для побудови об’єкта. Mapper з іншого боку повинен просто копіювати поля з одного в інше.

Наприклад, карта з об'єкта працівника бази даних до об’єкта працівника домену, карта від об’єкта працівника домену до договору клієнта.

З іншого боку, будівельники приймають безліч бізнес-рішень щодо створення об'єкта. З точки зору єдиної відповідальності, це має сенс.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.