2

以下は、.netFrameworkでのパターンの使用に関する記事です。以下の抜粋の太字部分がわかりません。オブジェクトの作成の詳細を変更した場合、コンストラクターの引数を変更する可能性があることを意味しますか?

フレームワークには、コンストラクターを自分で呼び出さなくても、構造体またはクラスの新しいインスタンスを取得できる場合が多くあります。System.Convertクラスには、このように機能する静的メソッドのホストが含まれています。たとえば、整数をブール値に変換するには、Convert.ToBooleanを呼び出して、整数を渡すことができます。このメソッド呼び出しの戻り値は、整数がゼロ以外の場合は「true」に設定され、それ以外の場合は「false」に設定された新しいブール値です。Convertクラスは、正しい値でブール値を作成します。他の型変換方法も同様に機能します。Int32およびDoubleのParseメソッドは、文字列のみが指定された適切な値に設定されたオブジェクトの新しいインスタンスを返します。

新しいオブジェクトインスタンスを作成するためのこの戦略は、ファクトリパターンとして知られています。オブジェクトのコンストラクターを呼び出すのではなく、オブジェクトファクトリにインスタンスの作成を依頼できます。このようにして、ファクトリクラスはオブジェクト作成の複雑さを隠すことができます(文字列からDoubleを解析する方法など)。オブジェクトの作成の詳細を変更したい場合は、ファクトリ自体を変更するだけで済みます。コンストラクターが呼び出されるコード内のすべての場所を変更する必要はありません。

差出人:http ://msdn.microsoft.com/en-us/magazine/cc188707.aspx

4

4 に答える 4

11

実際、彼らが提供した例は必ずしも素晴らしい例ではないと思います。

ファクトリパターンは、クラスを構築するときに.NETでより便利になります。たとえば、WebRequestクラスを見てください。

このクラスは通常、次の呼び出しによってインスタンス化されます。

WebRequest request = WebRequest.Create(url);

WebRequest.Createメソッドはファクトリパターンを使用しますURLのタイプに応じて、異なるタイプ(サブクラス)のWebRequestが作成されます。たとえば、URLを渡すと、http://実際にHttpWebRequestインスタンスが作成されます。URLによってFtpWebRequestftp://が作成されます。

ここでファクトリパターンを使用すると、クライアント側でコードを変更せずに、後でURLタイプを追加できます。別のURLを(文字列として)渡して、新しいオブジェクトを取得するだけです。

于 2009-12-08T20:18:06.037 に答える
2

ファクトリパターンは、私がプログラムで最もよく使用するパターンです。特定の場合に非常に役立ちますが、使用するときは必ず注意する必要があります。ファクトリがコンストラクタのオーバーロードのように見える場合は、おそらくコンストラクタのオーバーロードである必要があります。MSDNの記事で提供された例は良くありません。実際、Int、Stringなどのオブジェクトは、クラスではなく構造体であり、原則として、構造体コンストラクターは例外をスローしないため、相互にオーバーロードを考慮しないというのが私の信念です(これは、たとえば、「helloworld」をintにフィードできる場合に発生します)。しかし、私はそれを仮定しました。

もちろん、Webの周りには、ファクトリパターンをいつ使用するかとその利点についてのより良い説明を見つけることができる場所がたくさんあります。Reedの例は、最も優れた例の1つであり、ファクトリを使用するための私のルールに従います。特定のインターフェイスを実装するクラス階層または複数のクラスがあり、それらのオブジェクトの1つを構築したいが、オブジェクトを受け取る場合は、ファクトリを使用します。オブジェクト自体ではなく、スーパークラス/インターフェイスの そうすれば、ファクトリを呼び出しているオブジェクトは、実装の詳細について心配する必要がありません。それは特定のクラスのオブジェクトを期待していることを知っており、それがキャストであっても、それが得られるものです。

私が構築している現在のアプリケーション(プログラムジェネレーター)では、データテーブルSQL定義を解析する必要があります。私はそれを行うために自作のパーサーを使用します。パーサーが変数( "IDENTIFIER VARIABLE-TYPE")に遭遇するたびに、ファクトリを呼び出して文字列を渡します。次に、ファクトリは変数タイプのサブストリングをチェックし、SqlVariableを返しますこれは、実際にはIntegerSqlVariableまたはCharSqlVariableである可能性があります。

メインのパーサーオブジェクトは、取得した変数を認識していません。SqlVariableをリストにプッシュし、次の行を読み取ります。もちろん、すべての変数型を処理する単一のクラスを持つこともできます。私は個人的にそうしないことを選びます。

于 2009-12-08T20:56:04.353 に答える
2

工場の全体的な考え方は異なっているようです。実装の複雑さを隠すだけでなく、制御の反転(IoC)も重要です。

  • 独自のオブジェクトを作成するのではなく、Senderオブジェクトにそれらの作成を担当Receiverさせましょう。MessageFactory
  • TcpMessageFactory最初に(MessageFactory子孫の)作成オブジェクトを実装したTcpSenderと想像してみましょう。TcpReceiverこれで、アプリケーションはTCPで動作します。
  • 少し後に、UDPの方が高速であることがわかりました。そこで、実装UdpSenderUdpRecieverました。UdpMessageFactoryまた、 (MessageFactory子孫も)実装しました
  • これで、ユーザーが使用するプロトコルを選択できるようになりました。これに基づいて、ファクトリオブジェクト(TcpMessageFactoryまたはUdpMessageFactory)を作成し、アプリケーションでさらに使用します。

この例MessageFactory.CreateSenderMessageFactory.CreateRecieverは、抽象メソッドである必要があります。パブリックAPI(コントラクト)の作成方法も抽象化する必要がありますSenderReciever

ところで、当初はファクトリは主にオブジェクトの作成に使用されていました。メインの.exeに対して独自のタイプのセットを作成できるようにする必要があるC ++ライブラリ(DLL)を想像してみてください。異なるモジュール間でインスタンスを渡すことはほとんど不可能です。なぜなら、それらの構造は特定のコンパイラに依存しているからです。ただし、インターフェイスを渡すことは可能です。したがって、そのようなDLLは次のようになります。

  • ファクトリインターフェイスを返す関数をエクスポートします。例:IDllTypeFactory
  • それを実装するIDllTypeXxxオブジェクトは、そのCreateXxxメソッドの呼び出し時にオブジェクトを返す必要があります。これらIDllTypeXxxは、実際には、最初にエクスポートする予定のタイプによって実装されています。

しかし、ご存知のように、統一されたアセンブリ形式の.NETを使用すると、異なるモジュール間でオブジェクトを渡すことができます。さらに、リフレクションを使用すると、まったく知らないタイプを作成できます。そのため、.NETのファクトリはほとんど使用されません。

于 2009-12-08T20:57:04.010 に答える
0

はい、コンストラクターのオーバーロードを使用して、ソースコードのすべての領域を変更せずにコンストラクターを変更できますが、あまり注意しないと、すぐにとんでもない数のコンストラクターになります。

この記事の一般的な考え方は、コンストラクターの変更を説明するために、コンストラクターの大規模なオーバーロードを必ずしも防ぐのではなく、実装を隠すことだと思います。オブジェクトであるという考えは、それがどのように構築されるかについての知識を持っているべきではありません。

与えられた例では、文字列またはdoubleからintになる方法でIntクラスを詰まらせたくないので、YパラメータからXオブジェクトを作成することを唯一の責任とするファクトリを作成します。

デザインパターンを学ぶための良い入門書として、Head FirstDesignPatternsの本をぜひお勧めします。例はJavaベースですが、その背後にあるロジックは、使用している言語に関係なく適用されます。

于 2009-12-08T20:35:12.820 に答える