「マッパー」は有効な設計パターンですか、それとも「工場」パターンのバリエーションですか?


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;
    }
}

アイデアは、Gateway / DAO / Repository / etcになります。返される前にマッパーを呼び出すので、基になるデータコンテナに対してリッチビジネスオブジェクトを取得します。

ただし、これは同一ではないにしても、ドメインオブジェクトを構築して返すFactoryパターン(とにかくDDDの用語)に関連しているようです。ウィキペディアによると、これは次のとおりです:DDDファクトリー:

ファクトリ:ドメインオブジェクトを作成するメソッドは、代替の実装を簡単に交換できるように、専用のファクトリオブジェクトに委任する必要があります。

その引用から私が考えることができる唯一の違いは、「マッパー」が特定のクラスにキー設定されている間に、必要に応じて特別なタイプのオブジェクトを返すことができるようにDDDスタイルのファクトリーをパラメーター化できることです(たとえば、BusinessCustomer対ResidentialCustomer)そして翻訳のみを行います。

それで、これらの2つのパターンに違いはありますか、それとも異なる名前で本質的に同じものですか?


これはORMとは異なりますか?もしそうであれば、どこが違いますか?
JBキング

ORMはマッピングを自動的に処理します-これはORMを使用できない(または独自のデータレイヤー/シンORMを記述する必要がある)シナリオの場合です
ウェインモリナ

1
DataMapperが「まったく別のもの」であるかどうかを確認するのに本当に苦労しています。
pdr

たぶん私は間違っている-私はDataMapperパターンがデータベース自体にアクセスしたと思ったが、この「マッパー」はデータベースからプルせず、何らかの結果セットをオブジェクトに変換するだけです。
ウェインモリナ

martinfowler.com/eaaCatalog/dataMapper.htmlどういう意味かわかりましたが、最後の段落を読んで、それはほぼ正しいです。PEAAカタログをご覧ください。martinfowler.com/eaaCatalog/index.html。あなたが説明しているのは確かに一種のマッパーであり、残りよりもDataMapperにより密接に適合しています。
PDR

回答:


23

マッパーパターンを聞いたのはこれが初めてですが、私にとっては、ファクトリーというよりむしろビルダーパターンのように聞こえます。

Factoryパターンでは、多数の関連クラスのオブジェクトを作成するためのロジックをカプセル化します。主な例は、いくつかのパラメーターに応じて、いくつかの抽象基本クラスの特定のサブクラスのオブジェクトを作成する必要がある状況です。そのため、ファクトリは常に基本クラスへのポインタまたは参照を返しますが、実際には、与えられたパラメータに基づいて適切な派生クラスのオブジェクトを作成します。

対照的に、Builderクラスは常に同じクラスのオブジェクトを作成します。オブジェクトの作成が複雑な場合に使用します。たとえば、コンストラクターは多くの引数を取りますが、そのすべてがすぐに利用できるわけではありません。したがって、Builderオブジェクトは、コンストラクター引数の値をすべて保持して「製品」を作成する準備が整うまで、コンストラクター引数の値を格納する場所であるか、妥当なデフォルト値を提供し、必要な値を持つ引数のみを指定できる変化する。Builderパターンの一般的な使用例は、すべての作成ロジックでテストコードが乱雑になるのを避けるために、単体テストで必要になる可能性のあるオブジェクトを作成することです。

私には、マッパーは、ビルダーのバリアントのように聞こえます。コンストラクターのパラメーターは、データベースレコードまたはその他の「生の」データ構造の形をとります。


うーん、私はBuilderのことを聞いたことがありますが、それが何を伴うのかを100%認識していませんでした。主な違いは、Factoryが実際にパラメーターに基づいた具体的なクラスであるインターフェース/抽象クラスを返すように聞こえます(理にかなっている場合)。Builder/ Mapperは実際のデータを取得し、それらをプロパティにマップします。 ?
ウェインモリナ

1
@ウェインM:ほとんど。Builderには多くのロジックがありますが、データのプロパティへのマッピングはまったく簡単ではない可能性があります。実際、ビルダーには、パラメーターを作成する他のビルダーが含まれている場合があります。:)
ディマ

5
Builderパターンを使用すると、複雑な(通常は不変の)オブジェクトを構築するために必要なすべての情報を時間をかけて配置し、プロセスの最後にオブジェクトをインスタンス化できます。それはここで起こっていることではありません。
pdr

+1これは理にかなったアプローチであり、DTOオブジェクトとドメインモデルオブジェクト間のメディエーターとして機能する別個の「マッパー」クラスを持つことに同意しました。また、ドメインモデルオブジェクトを構築するときに特別な状態にする必要がある場合(つまり、.NET ISupportInitializeインターフェイス)に便利です。
MattDavey

@pdr、マッパーはビルダーとまったく同じではないことに同意します。すべてのデータが一度に利用できるからです。しかし、1つのタイプのオブジェクトのみを構築するため、非常に似ています。
ディマ

8

Mapper、Builder、およびFactoryについての唯一の共通点は、「構築された製品」とタイプのオブジェクトインスタンスを提供することです。混乱を避けるため、それぞれの定義については以下の説明を参照しています。

  1. マッパー-ここで説明されているものに近い:http://www.codeproject.com/KB/library/AutoMapper.aspx。これは上記とまったく同じではありませんが、最も近いのはマッパーについてです。

  2. ビルダー-ここで定義されているとおり:http : //www.oodesign.com/builder-pattern.html

  3. 工場-ここで定義されています:http : //www.oodesign.com/factory-pattern.html

マッパーは本質的に裏返しのコンストラクターです。マッパーを持っていない場合、しばらく考えてください-とにかく多くのパラメーターのセットが必要な場合、それらはすべてコンストラクターの引数です。状況が進化するにつれて、一部のアプリケーションは、計算するかデフォルトを使用するコンストラクタの下に行く必要がある追加の属性を認識しません。重要なことは、マッパーがこれをあなたのためにできるということです-そして、これが構築のためのそのようなアルゴリズムを決定するために外部オブジェクトへのリンクを持っているならば、それはより便利です。

Builderはマッパーとは大きく異なります。完全なオブジェクトがオブジェクトの多くの部分を使用して構成される場合、ビルダーは不可欠です。これは、多くの部品を組み合わせてオブジェクトを組み立てるようなものです。個々の部品オブジェクトの初期化でさえ、他の部品の存在に関連しています。

工場出荷時のパターンは、最初は非常にシンプルに見えます。新しく構築されたオブジェクトを返します。通常のコンストラクタでnew()などの演算子を使用して完全に機能するインスタンスを提供できる場合 同じ結果が得られる工場が必要なのはなぜですか?

ただし、ファクトリパターンの使用法は通常非常に限定的です。ただし、ほとんどの場合、これが適用される文献には表示されません。通常、アプリケーションは、実行中にそのような製品オブジェクトを作成する必要があるさまざまなオブジェクトに共有されるファクトリを作成します。そのような製品が多数作成されると、Factoryメソッドでは特定のポリシーに基づいてオブジェクトを作成できます。たとえば、すべてのオブジェクトが作成されるときにfactoryメソッドで使用される特定のテンプレートを強制できます。これは、ビルダーメソッドのようなものでもありません。ここでは、製品は1つだけです(独立しています)。これもマッパーとは異なります。ここでは、クライアントごとにオブジェクトを作成するための外部データセットは実際には最小限です。ファクトリパターンは、(名前が示すように)一貫して類似した製品オブジェクトを実際に提供します!

ディパン。



4

回答を見ると、回答者がすべて意味的に間違った回答を提供しているのがわかります。これは、あなたがすべての質問に集中しすぎているからだと思います。質問は、マッパーとファクトリーまたはビルダーとの関係に焦点を当てています。

実際、マッパーは工場やビルダーとは異なります。マッパーはアダプターに最も似ていますパターンにます(GoFの用語を使用)。アダプタパターンは、ある表現を別の表現に変換する機能を提供します。OPはADO.NETのDataSetとDataReaderを参照していましたが、SqlDataAdapterはどうですか?答えは名前にあります。マッパーは、長年プログラマーが長い間知っていたアダプタの新しい名前です。

マッパーは、ある表現を別の表現に変換します。これは、アダプターパターンの定義そのものです。


1

ここで行っているのは、実際には何らかの種類の変換です(生データをビジネスオブジェクトに変換します)。Factoryパターンを使用して厳密にそれを行う(つまり、型変換)ことができるので、何らかの方法で、クラスはファクトリーになります(ただし、Static Factoryを使用します)。


0

ビルダーは、複雑なビジネスロジックをカプセル化してオブジェクトを構築します。一方、マッパーはフィールドをあるフィールドから別のフィールドにコピーするだけです。

例のためのマップドメイン従業員オブジェクトへのデータベースのEmployeeオブジェクトから、マップクライアント契約へのドメインEmployeeオブジェクトから。

一方、ビルダーは、オブジェクトを構築するために複数のビジネス上の決定をホストします。単一責任の観点から、これは理にかなっています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.