ファクトリ メソッドは Smalltalk で使用されますか? もしそうなら、たとえば Java で使用する方法とは対照的に、どのように作成する必要がありますか? ありがとう。
2 に答える
ファクトリ パターンでは、サブクラスに名前を付けずにインスタンス化します。ピザ工場と階層を考えてみましょう:
Pizza
PepperoniPizza
CheesePizza
...
クラス名を知らずにピザのサブクラスをインスタンス化したいと考えています。例えば:
pizza := Pizza flavor: 'cheese' size: 12 inches
サイズが記入されたピザの正しいサブクラスを返します。
現在、Java または C++ では、異なる文字列名を比較するためにおそらく大きな「switch」ステートメントを実行するでしょう。Pizza の新しいサブクラスを追加するたびに、マスター switch ステートメントに忘れずに追加する必要があります。典型的な例については、ウィキペディアの記事を参照してください。
クラスがファースト クラス オブジェクトである Smalltalk ではそうではないため、各サブクラスに一致するように要求して、クラス階層を下に反復できます。例えば:
Pizza class>>flavor: aString size: anInteger
matchingClass := self subclasses detect: [:first | first matching: aString].
^matchingClass new size: anInteger.
そして、pizza の新しいサブクラスを実装するたびに、ファクトリ マッチングを行うメソッドを 1 つ実装します。
CheesePizza class>>matching: aString
^aString = 'cheese'
PepperoniPizza class>>matching: aString
^aString = 'pepperoni'
維持する中央スイッチ ステートメントはありません。ちょうどオブジェクト!
まず、Smalltalk ではコンストラクタに名前を付けました。実際、クラスはオブジェクトであり、「コンストラクター」は、たまたま新しいインスタンスを返すクラスで定義されたメソッドにすぎません。他の言語でのファクトリ メソッドの多くの使用法は、この方法でカバーできます。
例えば
Thing class >> withName: aString
^ dictionaryOfAllThings
at: aString
ifAbsentPut: (self new name: aString; yourself)
名前で物を取得し、その名前の物がまだ存在しない場合にのみ新しい物を作成します。