抽象ファクトリパターンはスケーリングしますか?


8

私はまだここでデザインパターンを理解しようとしています。抽象ファクトリパターンを学習した後、このパターンはうまくスケーリングしないことに気付きました。抽象ファクトリー・パターンのUMLダイアグラムを見てください。

UML図

新しい「AbstractProductC」を作成する必要がある場合は、ConcreateFactory1とConcreateFactory2の両方の実装に影響を与える「AbstractFactory」に抽象メソッド「CreateProductC」を追加する必要があります。

ここでの私の質問は、Abstract Factoryパターンはまったくスケールしますか(または)私はここで間違った方向に考えていますか?

前もって感謝します


あなたが提示した図は、比較的標準的に見えますが、問題のパターンを示すために簡略化されていると思います。ただし、より複雑なものが必要な場合は、常に1つのメソッドCreateProduct(productType)だけを定義したAbstractFactoryを使用して、ファクトリー内にファクトリーを作成し、タイプを調べて、それに基づいて具象クラスをインスタンス化することができます。
DXM

@DXMそれは問題を解決しません。新しい製品を追加するたびに、具体的なファクトリの実装を変更する必要があります。
陶酔

まあ、スケーリングするのは実際の抽象的なインターフェイスだけですが、ええ、N個の製品とそれらを作成するM個の方法がある場合、どのようにスライスしても、完全に異なる戦略を使用しない限り、N x Mの実装が必要です。
DXM

@ユーフォリック:必ずしもそうではありません。ファクトリクラスを追加して、それを抽象ファクトリに登録するだけで済みます。少しつまらないように見えるかもしれませんが、スケーリングとSRPの場合、変更を加えるよりも少し面倒を加えることがわかります。
Marjan Venema 2013

@MarjanVenemaここで問題は、それが本当にファクトリであり、異なるパターンではないかどうかです。
陶酔

回答:


5

Abstract Factoryは問題なく拡張できます。

クラスは一つのことをうまくやるべきだと述べている基本原則があります。ここでの問題は、多くのクラスに多くのことを実行させようとしていることです。

1つの抽象ファクトリに固執する必要はありません。あなたはいくつかのことができます(そして持っているべきです):

AbstractProductAFactoryProductAを作成するためのインターフェースを定義します。具体的な実装(ConcreteProductAFactory1、ConcreteProductAFactory2)はそれを拡張します。

AbstractProductBFactoryProductBを作成するためのインターフェースを定義します。具体的な実装(ConcreteProductBFactory1ConcreteProductBFactory2)はそれを拡張します。

次にProductCが必要な場合は、新しいを作成しますAbstractProductCFactory。この方法で他の工場を変更する必要はありません。

UPDATE 理想的には、ProductAは製品のクラス、つまり、ProductAと呼んでいるインターフェースを共有するすべての製品を表す必要があります。コメントで私はこれがピザのようなものであることを提案します:

interface AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings);
}


class ThinCrustPizzaFactory implements AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings){

        ...

    }
}

class DeepDishPizzaFactory implements AbstractPizzaFactory {
    public Pizza buildPizza(List<Topping> toppings){

        ...

    }
}

等々。PanPizzaFactoryを追加しても、他のクラスには影響しません。これは、PizzaFactoryの新しい具体的な実装にすぎません。ピザではない製品(サンドイッチなど)がある場合、そこに別の抽象ファクトリ(たとえばAbstractSandwichFactory)を作成します。

実際のポイントは、2つの異なる「ビルド」メソッドを使用して2種類の非常に異なるタイプの製品をビルドする抽象ファクトリーは必要ないということです。それらをできるだけ論理的にグループ化して、インターフェースを共有し、具体的なファクトリーがそのインターフェースの実装を構築する方法を定義する抽象ファクトリーを作成します。


4
冗談でしょ?あなたの会社が256の製品を作っているとしたら?それとも1024?
Robert Harvey

@RobertHarvey-ProductAが製品のクラスであると想定しています-AbstractPizzaFactoryであるとしましょう。これには、具体的なThinCrustPizzaFactory、具体的なPanPizzaFactory、具体的なDeepDishPizzaFactoryを含めることができます。同様に、サンドイッチは、AbstractSandwichFactoryのサブタイプによって構築されます。これは、buildPizzaとbuildSandwichメソッドの両方を持つAgrstractFactoryとは異なります。
マシューフリン

@RobertHarvey-一方、製品の微妙なバリエーション(トッピングなど)は、個別に処理できるものかもしれません。おそらくあなたのファクトリーメソッドはでしょうAbstractPizzaFactory.buildPizza(List<Topping> toppings)
マシューフリン

あなたはあなたの答えでそれらのことを明確にしたいと思うかもしれません。
Robert Harvey

@RobertHarvey-更新
Matthew Flynn

4

スケーリングの問題は、コードがさまざまな方法でスケーリングできることです。あなたが抱えている問題は、ある方向にスケーリングする必要性によって単に引き起こされ、その設計パターンは意図されていません。Abstract Factoryパターンの場合、新しいコンクリート工場を追加する方法でスケーリングすることを意図していますが、新しい製品を追加すると、大きな構造変化が発生します。

ソフトウェアの設計とアーキテクチャのポイントの1つは、コードがスケーリングする可能性が最も高い方向を特定し、それらの可能性のある方向に基づいてパターンを選択することです。特定した場合、新しい製品を追加することは新しいコンクリートファクトリを追加することよりも可能性が高いため、Abstract Factoryを使用することは良いアイデアではなく、設計を完全に再考する方が良いでしょう。


1
あなたの答えは、堅固な「抽象工場スケールファイン!」他の男の...
トルコ

@Euphoricは、あなたが提案しているように、新しいファクトリーパターンスケールは新しいコンクリート工場を追加する方法ですが、最終的に新しいコンクリートファクトリーは製品を生成する必要があります。正しい?
Jitendar 2013

@Jitendarどういう意味かわかりません。抽象ファクトリーのポイントは、関連する抽象化(ProductA、ProductB)の比較的安定したファミリーがあり、具体的なファクトリーがそれらの抽象化の実装を作成することです。新しい抽象化を追加する可能性が、それらの抽象化の新しい具体的な実装を追加するよりも高い場合は、抽象ファクトリを使用することは適切ではありません。
陶酔

3

はい、そうです。追加の抽象製品が必要な場合、「抽象ファクトリ」は適切に拡張されません。

しかし、実際の多くのシナリオでは、製品の数が変化していますが、サポートする抽象製品の数はわずかに決まっています。たとえば、抽象ファクトリーに関するウィキペディアの記事の GUIウィジェットの例を見てみましょう。抽象GUIファクトリーは、メソッドをcreateWidget(の代わりにcreateButton)持つことができます。ここWidgetで、は「抽象製品」であり、数十のGUI要素のファミリーの最上位の基本クラスになります。新しいGUIウィジェットを追加しても、抽象ファクトリのインターフェースが変更されることはありません。そのため、具象ファクトリのインターフェースを変更する必要はありません。

抽象製品がたくさんあるということは、コードにさまざまなクラス階層がたくさんあることを意味します。その場合は、階層ごとに個別のファクトリ(または抽象ファクトリ)を作成することを検討してください。


0

スケーリング係数は、依存関係管理の単純な問題です。クラスがより多くの依存関係を持つ-そのAPIはより安定していて、思慮深いはずです。

類似した、まとまりのある性質のタイプを作成する責任によって定義されるファクトリーの作成には問題はありません。しかし、このファクトリーに依存するクラスが多いほど、この凝集はより厳密になるはずです。

(注:これは段階的に行うことができ、必ずしもBDUFで行う必要はありません)

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