私はパターンを設計するのが初めてで、ファクトリーメソッドとストラテジーのパターンを自分の方法で処理します。 Factoryは創造的なパターンであり、Strategyは行動であると理解していますが、どのパターンをいつ使用するかを理解するのに苦労しています。たとえば、指定した会社に基づいてクライアントの詳細を更新する次のクラスがあります。
public interface IUpdateDetails { void UpdateDetails(); }
public class UPSUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Call web service to update details for UPS...");
}
public class FedExUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Update database for FedEx...");
}
public class DHLUpdateDetails : IUpdateDetails
{
public void UpdateDetails() => Console.WriteLine("Send Email for DHL...");
}
正しいクラスを返すファクトリを作成できます。
public class UpdateDetailsFactory
{
public static IUpdateDetails Create(string type)
{
switch (type)
{
case "UPS":
return new UPSUpdateDetails();
case "DHL":
return new DHLUpdateDetails();
case "FedEx":
return new FedExUpdateDetails();
default:
throw new ArgumentException();
}
}
}
次のように実装します。
// Using Factory
string company = "UPS"; // Get company from database
IUpdateDetails updateDetails = UpdateDetailsFactory.Create(company);
updateDetails.UpdateDetails();
Console.ReadLine();
または私は戦略パターンを使うことができます:
public class UpdateDetailsContext
{
private IUpdateDetails strategy;
public void SetStrategy(IUpdateDetails updateDetails) => strategy = updateDetails;
public void Update() => strategy.UpdateDetails();
}
次のように実装します。
// Using Strategy
UpdateDetailsContext context = new UpdateDetailsContext();
context.SetStrategy(UpdateDetailsFactory.Create(company));
context.Update();
Console.ReadLine();
私の質問は-パターンを正しく理解していますか?どちらを使用するかとの違いは何ですか?
私の質問は-パターンを正しく理解していますか?
主に。ファクトリの実装は正しいですが、UpdateDetails
だけが異なるため、少し奇妙です。このようなことは、戦略(C#の単純なラムダ)として行う方が適切です。実際には、工場は具体的な実装を少し変える傾向があります-パターンの違いをより明確にします。
どちらを使用するかとの違いは何ですか?
一般に、戦略はby他のオブジェクトを使用します。あなたは彼らに戦略を与え、彼らはそれが何をするかを必ずしも知らないでそれをします。あなたはあなたの行動を柔軟にしたいときに使います。
ファクトリー提供するランタイム入力に基づく不明なオブジェクトを使用します。実行時に結果を変化させたい場合に使用します。ただし、通常は、ファクトリで構築できる固定されたセットがあります。条件付き作成を抽象化することよりも、柔軟性を求めることはありません。
そして、パターンは主にcommunicationのためのものであることを覚えておいてください。戦略とファクトリーパターンを使用して同じことを達成できるとしても、他の開発者と通信するとき、それらは異なることを意味します。ファクトリーは明らかに「私はいくつかのものを作成しています」が、戦略はやや明確ではない「私はあなたにいくつかの動作を指定させています」。
問題によく適合する複数のパターンがある場合、パターン間の主な違いは、パターンの使用をどのように想定するかです。多くの場合、パターンは孤立して存在せず、一方が他方より好ましいかどうかに影響を与える他の設計原則とともに使用されます。
たとえば、定義したファクトリパターンは、正しいバージョンのIUpdateDetails
実装があることを確認するのにまったく問題ありません。 Dependency Injectionベースのアプリケーションは通常、ファクトリを実装するため、実際に使用する必要がある場合に、正しい実装を自動的にワイヤリングできます。ファクトリを定義したのと同じように、実際にファクトリが必要になる場合もあります。
使用例が単純な場合(提供された例のように)、戦略パターンの利点はありません。追加のメリットがないため、少し作業が増えます。ただし、この例をさらに拡張すると、もう少し価値があることがわかります。
これを具体化しましょう:
class ShippingContext
{
private IUpdateDetails updateDetails;
private IQueryHistory queryHistory;
private string trackingNumber;
private string currentLocation;
public ShippingContext(string trackingNumber)
{
this.trackingNumber = trackingNumber;
var company = ShippingFactory.DetectCompany(trackingNumber);
queryHistory = ShippingFactory.CreateHistoryTracker(company);
updateDetails = ShippingFactory.CreateDetailsUpdater(company);
}
public TrackingHistory RetrieveHistory()
{
var history = queryHistory.Retrieve(trackingNumber);
lastLocation = history.Current.Location;
return history;
}
public void UpdateDetails()
{
updateDetails.Update(trackingNumber, lastLocation);
}
}
この場合、使用しているいくつかのクラスのすべての詳細とそれらを調整する方法を隠します。公開されているのは、既知の追跡番号に対して同じ作業を行っているという事実だけです。
var context = new ShippingContext("1Z9999999999999999");
var history = context.RetrieveHistory();
// do some extra things with history, or display it on screen
context.UpdateDetails();
Console.ReadLine();
戦略パターンが提供するものは、物事と相互作用する方法に関する段階的なプロセスです。背後で何が必要かについての詳細は、ユーザーに代わって処理されます。
パターンを正しく理解していますか?
はい。私はあなたの実装が理論的に理論的に完璧に見えると思います。
どちらを使用するかとの違いは何ですか?
何も言わない方がいい...
「secret」をお話ししましょう。
その結果、あなたのコードはあなたがあなたの心の中にあるものの物語であるはずです。 技術的な詳細は最終的には書き込まれますが、それらは可能な限り見えないところに隠されます。
戦略パターンで実行できることは何でも、ファクトリパターン(および他の多くのパターン)でも実行できます。選択は、次の経験則に基づいて行う必要があります。
そして、「変ではない」とは、もちろん、モデル化された現実(つまり、物語)に最もよく一致するものを意味します。これがコードをよりよく理解する方法であるため、可能な限り最も表現力豊かな方法でコードを記述することを選択します。これは、パターンが出現した方法です...実際のアイデアをコードに変換することによって。したがって、パターンから選択する方法は、問題をより直感的に表現するかを考えることです。
ですから... UpdateDetails
はクラスです(OK、インターフェースの後ろに隠されています)。それはrepresentsオブジェクトです。そのようなオブジェクトの意味は何ですか?私がそれを読んだ方法では、自然言語の物語では、それはオブジェクトよりもアクションを思い出させます(それは動詞であるため)。アクションをオブジェクトとして表現することはすでに混乱しているので、ファクトリーは物事をさらに複雑にするだけです。これは、工場を使用する場合、もう話の内容がはっきりしないことを意味します。
したがって、質問に直接回答するには、次の場合にファクトリを使用します。
次の場合に戦略を使用します。
これはすべて、「高い」規則によるのではなく、コードを実際の状況の「ナラティブ」にしたため、より多くの人々がそれを解釈できるようになります(将来の自己を含め、戻ってきたとき)あなた自身のコードに、あなたが何をするつもりだったかを思い出そうとしてください)、それでその表現力を高めます!
これらは多くの類似点があることは正しいです。他の回答で述べたように、違いは目標です。
Strategyパターンは誤解されがちですが、コードを簡略化するための最も価値のあるパターンの1つでもあります。パターンの鍵は、実行時にオブジェクトの動作を変更できるようにすることです。この良い例を考えるために、プレイヤーではない敵と何らかの戦いをしているビデオゲームを考えてみましょう。ある時点で、敵の「健康」を一定のレベルまで下げると、敵は「戦闘」モードから「飛行」モードに変わります。今、あなたはそれがどのモードにあるかをチェックするために至る所にバジリオンifステートメントを置くことができましたが、それは巨大な混乱です。代わりに、戦略パターンを使用して、オブジェクトとして表される一連の異なる動作定義を用意します。 「健康」レベルに応じて、正しい動作が使用されます。
これはビデオゲームだけに当てはまるわけではありません。注文システムがあり、セカンダリクラウドプロバイダーにフォールバックするための要件が与えられているとしましょう(たとえば、より高価ですが信頼性が高いとしましょう)。戦略パターンを使用して、その正気を保つことができます。
ファクトリー・メソッド・パターンは、コンストラクターに代わる素晴らしいものです。この良い例は、値0または1を渡すたびに同じオブジェクトを返す整数ファクトリーのようなものです。
重要なのは、これらを実際にさまざまな方法で組み合わせることができることです。たとえば、戦略パターンを使用して、作成するオブジェクトを決定するファクトリメソッドを作成できます。たとえば、上記の注文システムの例でこれを使用して、状況に応じて異なるDB接続オブジェクトを返すことができます。
一般的な見解は、「パターンは説明的なものであり、説明的なものではない」です。つまり、これらはレシピではなく、設計アプローチを説明する方法です。よくある間違いは、レゴのようにそれらを使用してソリューションを構築しようとすることです。
Factoryパターンは、対象となる特定のインターフェースを実装する型のインスタンスを作成するときに(つまり、必要なインターフェースを実装するものを作成するときに)使用することを目的としています。 Factoryパターンは、インターフェース実装が作成された方法のすべての不要な詳細を隠します。したがって、インターフェースを実装する「もの」を実際に使用する残りのコードに影響を与えることなく(またはほとんどなしに)後で必要に応じて変更できます。実際のファクトリーは、インターフェース実装の作成ロジックが、実装インスタンスを正確に作成する方法に関する「ヒント」を必要とするかどうかに応じて、パラメーターなしまたはパラメーター化されます。
戦略パターンは、必要に応じて予想されるアクション/操作の実装を簡単に変更できるようにすることを目的としています。各代替案は、「類似した」アクション/操作を実装するさまざまな関連する戦略タイプによって実装されます。一方、ファクトリの実装では、通常、同じファクトリが(いくつかの条件、パラメーター、事前構成に基づいて)期待される/要求されたインターフェースの代替実装を生成できると想定しています。
両方のパターンは、より複雑なシナリオで一緒に使用できます。たとえば、ファクトリーがストラテジーを使用して決定を行った後、期待されるインターフェース実装オブジェクトの実際の構築を特定のストラテジーに委任するために、ファクトリーはストラテジーのコレクションを内部で使用します。中古。しかし、この方法で呼び出されたFactoryは、戦略が背後で呼び出されることを認識していません。