これらのデザインパターンをn層アーキテクチャで使用できるシナリオはどれですか。
8 に答える
DTO は、システムの境界で使用できるオブジェクトです。たとえば、SOAP Web サービスがあり、応答を返したい場合は、DTO を使用します。ネットワーク経由で返さなければならない実際の XML よりも扱いが簡単です。DTO は、多くの場合、WSDL などに基づいてツールによって生成されます。DTO は多くの場合、サービス コンシューマのニーズに合わせて調整され、パフォーマンス要件の影響を受ける可能性があります。
一方、値オブジェクトはシステムのコアに存在します。ビジネスロジックの一部と、場合によってはフォーマットルールをキャプチャします。これにより、コードがより型安全で表現力豊かになります。「プリミティブ・オブセッション」のアンチパターンにも取り組みます。良い例は、文字列の代わりにクラス "SocialSecurityNumber" を使用することです。または小数の代わりにお金。これらのオブジェクトは、プリミティブのように見え、異なるスレッド間で簡単に共有できるように、不変でなければなりません。
たとえば、架空の「顧客注文」システムでは次のようになります。
CustomerAndLastFiveOrdersは DTO です (複数のネットワーク呼び出しを避けるために最適化されています)
顧客はエンティティです
MoneyとSKUは Value オブジェクトです
DTO オブジェクトと値オブジェクトを比較することは、オレンジとリンゴを比較するようなものです。
それらは完全に異なる状況に役立ちます。DTO は、データがレイヤー間で転送される方法のオブジェクト/クラス構造を定義し、値オブジェクトは、値が比較されるときの等価のロジックを定義します。
例を挙げて説明しましょう。まず最初に値オブジェクトを理解してみましょう:-
値オブジェクトは、同一性ではなく値に基づくオブジェクトです。
1 つは 1 ルピー硬貨で、もう 1 つは 1 ルピー紙幣です。
Money OneRupeeCoin = new Money();
OneRupeeCoin.Value = 1;
OneRupeeCoin.CurrencyType = "INR";
OneRupeeNote.Material = "Coin";
Money OneRupeeNote = new Money();
OneRupeeNote.Value = 1;
OneRupeeCoin.CurrencyType = "INR";
OneRupeeNote.Material = "Paper";
上記のオブジェクトを比較すると、現実世界では 1 ルピー紙幣は 1 ルピー硬貨に等しいため、以下の比較は true と評価されるはずです。
したがって、「==」演算子を使用しているか、「Equals」メソッドを使用しているかのいずれかで、比較は true と評価されます。デフォルトでは、「==」または「equals」は true と評価されないため、目的の動作を得るには、演算子のオーバーライドとメソッドのオーバーライドを使用する必要があります。同じことを達成する方法を説明するこのリンクを見ることができます。
if (OneRupeeCoin==OneRupeeNote)
{
Console.WriteLine("They should be equal");
}
if (OneRupeeCoin.Equals(OneRupeeNote))
{
Console.WriteLine("They should be equal ");
}
通常、値オブジェクトは不変性の良い候補です。詳細については、こちらをご覧ください。不変オブジェクトを作成する方法を説明するこのビデオを見ることができます。
それでは、DTO を理解してみましょう:-
DTO (データ転送オブジェクト) は、レイヤー間のデータ転送を簡素化して移動するためのデータ コンテナーです。
それらは転送オブジェクトとも呼ばれます。DTO はデータの受け渡しのみに使用され、ビジネス ロジックは含まれません。シンプルなセッターとゲッターしかありません。
たとえば、顧客データを取得するための呼び出しと、製品データを取得するための呼び出しの 2 つを行っている以下の呼び出しについて考えてみましょう。
DataAccessLayer dal = new DataAccessLayer();
//Call 1:- get Customer data
CustomerBO cust = dal.getCustomer(1001);
//Call 2:- get Products for the customer
ProductsBO prod = dal.getProduct(100);
したがって、以下に示すように、Customer クラスと Product クラスを 1 つのクラスに結合できます。
class CustomerProductDTO
{
// Customer properties
public string CustomerName { get; set; }
// Product properties
public string ProductName { get; set; }
public double ProductCost { get; set; }
}
1 回の呼び出しで、顧客データと製品データの両方を取得できるようになりました。データ転送オブジェクトは、2 つのシナリオで使用されます。1 つはリモート呼び出しを改善するため、もう 1 つはオブジェクト階層を平坦化するためです。データ転送オブジェクトについて詳しく説明しているこの記事を読むことができます。
//Only one call
CustomerProductDTO cust = dal.getCustomer(1001);
以下は完全な比較シートです。
ここにはいくつかの良い答えがありますが、重要な違いを捉えるために 1 つ追加します。
値オブジェクトには ID がありません。つまり、同じ値を含む値オブジェクトの 2 つのインスタンス間の比較は、それらが等しいことを示す必要があります。データ転送オブジェクトは、値を保持するためにのみ使用されますが、ID を持っています。同じ値を持つが、個別に作成された DTO の 2 つのインスタンスを比較しても、それらが等しいことは示されません。
例:
DTO dto1 = new DTO(10);
DTO dto2 = new DTO(10);
dto1.equals(dto2); //False (if equals is not overridden)
dto1 == dto2; //False
VO vo1 = VO.getInstance(10);
VO vo2 = VO.getInstance(10);
vo1.equals(vo2); //True
vo1 == vo2; //True
== 演算子は常にオブジェクト ID を比較するため、Java で Value Object パターンを実装するのは少し難しいです。これを行う 1 つの方法は、各値に対して同じオブジェクトを返すオブジェクト キャッシュを実装することです。
public class VO {
Map<Integer, WeakReference<VO>> cache = new LinkedHashMap<Integer, WeakReference<VO>>();
public static VO getInstance(int value) {
VO cached = cache.get(value);
if(cached == null) {
cached = new VO(value);
cache.put(value, new WeakReference<VO>(cached));
}
return cached.get();
}
private int value;
private VO(int value) {
this.value = value;
}
}
値オブジェクトは、オブジェクトとしてカプセル化するのに役立つものですが、アイデンティティはありません。それを実体と比較してください。それはアイデンティティを持っているものです。したがって、注文処理システムでは、Customer、Order、またはLineItemは特定の人、物、またはイベントを指す概念であるため、値オブジェクトが金額のようなものであり、独自の独立した存在。たとえば、アプリケーションの一部で支払いを異なるアカウント間で分割する方法を計算するシステムの場合、元のオブジェクトの金額を均等に分割するMoneyオブジェクトの配列を返すdivideメソッドを持つ不変のMoneyオブジェクトを作成しました。金額を分割するためのコードは、jspを書いている人がそれを使用できる便利な場所にありました。
データ転送オブジェクトは、アプリケーションの階層またはレイヤー間で送信するために物事をバンドルするためのラッパーです。大量の情報を送信するメソッドを設計することにより、ネットワークの往復トラフィックの量を最小限に抑えるという考え方です。
データ転送オブジェクトに反対することをお勧めします。私の意見では、これは EJB 1.0 のアンチパターンであり、層の純粋性を主張する人々によって価値が与えられています。
値オブジェクトは便利です。これは通常、Money などの不変オブジェクトです。それらはスレッドセーフである必要があります。