542

これら2つのパターンの違いについて多くの投稿があることは知っていますが、見つけられないことがいくつかあります。

私が読んでいることから、ファクトリメソッドパターンを使用すると、単一の具体的な製品を作成する方法を定義できますが、一般的な製品が表示されるため、クライアントから実装を隠すことができます。私の最初の質問は、抽象ファクトリについてです。単一のコンクリートオブジェクトではなく、(使用する特定のファクトリに応じて)コンクリートオブジェクトのファミリを作成できるようにする役割はありますか?抽象ファクトリは、呼び出すメソッドに応じて、1つの非常に大きなオブジェクトまたは多数のオブジェクトのみを返しますか?

私の最後の2つの質問は、私が多くの場所で見たことを完全には理解できない単一の引用についてです。

2つの違いの1つは、抽象ファクトリパターンでは、クラスがオブジェクトのインスタンス化の責任をコンポジションを介して別のオブジェクトに委任するのに対し、ファクトリメソッドパターンは継承を使用し、サブクラスに依存して目的のオブジェクトのインスタンス化を処理することです。

私の理解では、ファクトリメソッドパターンには、どのConcreteProductをインスタンス化するかをConcreteCreatorが認識できるようにするCreatorインターフェイスがあります。これは、継承を使用してオブジェクトのインスタンス化を処理することの意味ですか?

さて、その引用に関して、Abstract Factoryパターンは、オブジェクトのインスタンス化の責任をコンポジションを介して別のオブジェクトにどの程度正確に委任しますか?これは何を意味するのでしょうか?Abstract Factoryパターンも、私の目には継承を使用して構築プロセスを実行しているように見えますが、それでも私はこれらのパターンについてまだ学習しています。

特に最後の質問で助けていただければ幸いです。

4

22 に答える 22

599

2つの違い

「ファクトリメソッド」と「抽象ファクトリ」の主な違いは、ファクトリメソッドがメソッドであり、抽象ファクトリがオブジェクトであるということです。多くの人がこの2つの用語を混同し、同じ意味で使い始めていると思います。それらを学んだとき、違いが何であるかを正確に見つけるのに苦労したことを覚えています。

ファクトリメソッドは単なるメソッドであるため、サブクラスでオーバーライドできます。したがって、見積もりの​​後半は次のようになります。

...ファクトリメソッドパターンは継承を使用し、サブクラスに依存して目的のオブジェクトのインスタンス化を処理します。

引用は、オブジェクトがここで独自のファクトリメソッドを呼び出していることを前提としています。したがって、戻り値を変更できるのはサブクラスだけです。

抽象ファクトリは、複数のファクトリメソッドを持つオブジェクトです。あなたの見積もりの​​前半を見てください:

... Abstract Factoryパターンを使用すると、クラスはオブジェクトのインスタンス化の責任をコンポジションを介して別のオブジェクトに委任します...

彼らが言っているのは、Fooオブジェクトを作成したいオブジェクトAがあるということです。Fooオブジェクト自体を作成する代わりに(たとえば、ファクトリメソッドを使用して)、別のオブジェクト(抽象ファクトリ)を取得してFooオブジェクトを作成します。

コード例

違いを示すために、使用中のファクトリメソッドを次に示します。

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

そして、ここに使用中の抽象ファクトリがあります:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here
于 2011-04-21T05:39:37.590 に答える
142

抽象ファクトリは、作成する必要のあるオブジェクトのメソッドを定義する抽象メソッドを使用して基本クラスを作成します。基本クラスを派生させる各ファクトリクラスは、各オブジェクトタイプの独自の実装を作成できます。

ここに画像の説明を入力してください

ファクトリメソッドは、クラス内にオブジェクトを作成するために使用される単純なメソッドです。通常、集約ルートに追加されます(クラスには)OrderというメソッドがありますCreateOrderLine

ここに画像の説明を入力してください

抽象ファクトリ

以下の例では、キューの作成をメッセージングシステムから切り離すことができるようにインターフェイスを設計しているため、コードベースを変更せずにさまざまなキューシステムの実装を作成できます。

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

ファクトリメソッド

HTTPサーバーの問題は、すべての要求に対して常に応答が必要なことです。

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

ファクトリメソッドがないと、HTTPサーバーユーザー(つまりプログラマー)は、インターフェイスの目的を損なう実装固有のクラスを使用することを余儀なくされIHttpRequestます。

したがって、応答クラスの作成も抽象化されるように、ファクトリメソッドを導入します。

概要

違いは、ファクトリメソッドを含むクラスの意図された目的はオブジェクトを作成することではなく、抽象ファクトリはオブジェクトを作成するためにのみ使用されるべきであるということです。

オブジェクトを作成するときにLSP(リスコフの置換原則)を破るのは簡単なので、ファクトリメソッドを使用するときは注意が必要です。

于 2011-04-21T05:48:41.187 に答える
127

AbstractFactoryとFactoryのデザインパターンの違いは次のとおりです。

  • Factory Methodは、1つの製品のみを作成するために使用されますが、Abstract Factoryは、関連製品または依存製品のファミリーを作成することを目的としています。
  • ファクトリメソッドパターンは、オブジェクトを作成するためのメソッドをクライアントに公開しますが、抽象ファクトリの場合は、これらのファクトリメソッドで構成される可能性のある関連オブジェクトのファミリを公開します。
  • Factory Methodパターンは、単一のオブジェクトの構築を非表示にしますが、 Abstract Factoryは、関連するオブジェクトのファミリーの構築を非表示にします。抽象ファクトリは通常、(一連の)ファクトリメソッドを使用して実装されます。
  • 抽象ファクトリパターンは、コンポジションを使用してオブジェクトを作成する責任を別のクラスに委任しますが、ファクトリメソッドデザインパターンは継承を使用し、派生クラスまたはサブクラスに依存してオブジェクトを作成します。
  • ファクトリメソッドパターンの背後にある考え方は、クライアントが実行時に作成する必要のある具体的なクラスを知らないが、抽象ファクトリ パターンがシステムで複数の製品ファミリーを作成する必要がある場合、または実装の詳細を公開せずに製品のライブラリを提供する場合に最適です。

ファクトリメソッドパターンの実装: ファクトリメソッドUML

抽象ファクトリパターンの実装:

抽象ファクトリUML

于 2013-10-28T09:17:34.543 に答える
64

AbstractFactoryとFactoryMethodの主な違いは、AbstractFactoryがCompositionによって実装されることです。ただし、ファクトリメソッドは継承によって実装されます。

はい、あなたはそれを正しく読んでいます:これらの2つのパターンの主な違いは、古い構成と継承の議論です。

UMLダイアグラムは、(GoF)ブックにあります。このスレッドの上位2つの回答の例を組み合わせると、どちらかの回答だけよりも優れたデモンストレーションが得られると思うので、コード例を提供したいと思います。さらに、クラス名とメソッド名に本の用語を使用しました。

抽象ファクトリ

  1. ここで把握する最も重要なポイントは、抽象ファクトリがクライアントに注入されることです。これが、AbstractFactoryがCompositionによって実装されていると言う理由です。多くの場合、依存性注入フレームワークがそのタスクを実行します。ただし、DIにはフレームワークは必要ありません。
  2. 2番目の重要なポイントは、ここでの具体的なファクトリはファクトリメソッドの実装ではないということです。ファクトリメソッドのサンプルコードを以下に示します。
  3. 最後に、注意すべき3番目のポイントは、製品間の関係です。この場合、アウトバウンドキューと応答キューです。1つの具体的なファクトリはAzureキューを生成し、もう1つはMSMQを生成します。GoFは、この製品関係を「ファミリ」と呼びます。この場合のファミリは、クラス階層を意味するものではないことに注意することが重要です。
public class Client {
    private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }

    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }

    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }
}

public interface AbstractFactory_MessageQueue {
    OutboundQueue createProductA();
    ReplyQueue createProductB();
}

public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new AzureMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }
}

public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue {
    @Override
    public OutboundQueue createProductA() {
        return new MsmqMessageQueue();
    }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }
}

ファクトリメソッド

  1. ここで把握する最も重要なポイントは、ConcreteCreator クライアントであるということです。つまり、クライアントは、親がを定義するサブクラスですfactoryMethod()。これが、ファクトリメソッドが継承によって実装されていると言う理由です。
  2. 2番目の重要なポイントは、ファクトリメソッドパターンはテンプレートメソッドパターンの特殊化にすぎないことを覚えておくことです。2つのパターンは同じ構造を共有しています。それらは目的が異なるだけです。ファクトリメソッドは創造的(何かを構築する)ですが、テンプレートメソッドは動作的(何かを計算する)です。
  3. そして最後に、注意すべき3番目のポイントは、Creator(親)クラスが独自のを呼び出すことfactoryMethod()です。親クラスから削除 anOperation()し、メソッドを1つだけ残すと、ファクトリメソッドパターンではなくなります。つまり、ファクトリメソッドは親クラスの2つ未満のメソッドで実装することはできません。そして、一方が他方を呼び出す必要があります。
public abstract class Creator {
    public void anOperation() {
        Product p = factoryMethod();
        p.whatever();
    }

    protected abstract Product factoryMethod();
}

public class ConcreteCreator extends Creator {
    @Override
    protected Product factoryMethod() {
        return new ConcreteProduct();
    }
}

その他 &雑貨ファクトリパターン

GoFは2つの異なるファクトリパターンを定義していますが、存在するファクトリパターンはこれらだけではないことに注意してください。それらは必ずしも最も一般的に使用されるファクトリパターンでさえありません。有名な3番目の例は、EffectiveJavaのJoshBlochの静的ファクトリパターンです。Head First Design Patternsの本には、SimpleFactoryと呼ばれるさらに別のパターンが含まれています。

すべてのファクトリパターンがGoFのものと一致する必要があると想定するという罠にはまらないでください。

于 2018-06-10T17:04:41.717 に答える
37

Abstract Factoryは関連製品を作成するためのインターフェースですが、FactoryMethodは1つの方法にすぎません。抽象ファクトリは、複数のファクトリメソッドで実装できます。

抽象ファクトリUML

于 2013-12-18T02:19:14.427 に答える
14

理解しやすいように、この例を検討してください。

電気通信会社は何を提供していますか?たとえば、ブロードバンド、電話回線、モバイルなど、顧客に製品を提供するためのアプリケーションを作成するように求められます。

一般に、ここで行うことは、ブロードバンド、電話回線、モバイルなどの製品の作成は、ファクトリメソッドを使用して行うことです。ファクトリメソッドでは、これらの製品にどのようなプロパティがあるかがわかり、非常に簡単です。

現在、同社は顧客にブロードバンド、電話回線、モバイルなどの製品のバンドルを提供したいと考えており、ここに抽象ファクトリが登場します。

つまり、 Abstract Factoryは、独自の製品の作成を担当する他の工場の構成であり、Abstract Factoryは、独自の責任に関してこれらの製品をより意味のあるものにする方法を知っています。

この場合、はBundleFactory抽象ファクトリ、、、BroadbandFactoryはです。さらに単純化するために、これらのファクトリには、個々の製品を初期化するファクトリメソッドがあります。PhonelineFactoryMobileFactoryFactory

以下のコードサンプルを参照してください。

public class BroadbandFactory : IFactory {
    public static Broadband CreateStandardInstance() {
        // broadband product creation logic goes here
    }
}

public class PhonelineFactory : IFactory {
    public static Phoneline CreateStandardInstance() {
        // phoneline product creation logic goes here
    }
}

public class MobileFactory : IFactory {
    public static Mobile CreateStandardInstance() {
        // mobile product creation logic goes here
    }
}

public class BundleFactory : IAbstractFactory {

    public static Bundle CreateBundle() {
        broadband = BroadbandFactory.CreateStandardInstance();
        phoneline = PhonelineFactory.CreateStandardInstance();
        mobile = MobileFactory.CreateStandardInstance();

        applySomeDiscountOrWhatever(broadband, phoneline, mobile);
    }

    private static void applySomeDiscountOrWhatever(Broadband bb, Phoneline pl, Mobile m) {
        // some logic here
        // maybe manange some variables and invoke some other methods/services/etc.
    }
}

お役に立てれば。

于 2016-10-01T15:10:18.463 に答える
10

ファクトリメソッドは継承に依存しています。オブジェクトの作成はサブクラスに委任され、サブクラスはオブジェクトを作成するためのファクトリメソッドを実装します。

Abstract Factoryは、オブジェクト構成に依存しています。オブジェクトの作成は、ファクトリインターフェイスで公開されているメソッドで実装されます。

ファクトリおよびアブストラクトファクトリパターンのハイレベルダイアグラム、

ダイアグラム

Factoryメソッドの詳細については、この記事を参照してください。

抽象ファクトリメソッドの詳細については、この記事を参照してください。

于 2019-04-05T09:25:21.197 に答える
7

実際の例。(覚えやすい)

工場

あなたが家を建てていて、ドアを求めて大工に近づいたと想像してみてください。あなたはドアとあなたの要件の測定値を与えます、そして彼はあなたのためにドアを建設します。この場合、大工はドアの工場です。仕様は工場への入力であり、ドアは工場からの出力または製品です。

抽象ファクトリ

ここで、ドアの同じ例を考えてみましょう。あなたは大工に行くことができます、あるいはあなたはプラスチックのドア店またはPVC店に行くことができます。それらはすべてドア工場です。状況に応じて、どのような工場にアプローチする必要があるかを決定します。これはAbstractFactoryのようなものです。

ここでは、ファクトリメソッドパターンと抽象ファクトリパターンの両方を、問題を説明するために使用しないことから始めて、上記のパターンを使用して問題を解決することから説明しました https://github.com/vikramnagineni/Design-Patterns/tree/master

于 2017-11-23T10:25:44.720 に答える
3
  1. 私の最初の質問は、抽象ファクトリについてです。単一のコンクリートオブジェクトではなく、(使用する特定のファクトリに応じて)コンクリートオブジェクトのファミリを作成できるようにする役割はありますか?

はい。AbstractFactoryの目的は次のとおりです。

具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリを作成するためのインターフェイスを提供します。


  1. 抽象ファクトリは、呼び出すメソッドに応じて、1つの非常に大きなオブジェクトまたは多数のオブジェクトのみを返しますか?

理想的には、クライアントが呼び出しているメソッドごとに1つのオブジェクトを返す必要があります。

  1. 私の理解では、ファクトリメソッドパターンには、どのConcreteProductをインスタンス化するかをConcreteCreatorが認識できるようにするCreatorインターフェイスがあります。これは、継承を使用してオブジェクトのインスタンス化を処理することの意味ですか?

はい。ファクトリメソッドは継承を使用します。

  1. 抽象ファクトリパターンは、オブジェクトのインスタンス化の責任をコンポジションを介して別のオブジェクトに委任しますか?これは何を意味するのでしょうか?

AbstractFactoryはFactoryMethodを定義し、ConcreteFactoryはConcreteProductの構築を担当します。 この記事のコード例に従ってください。

詳細については、関連するSEの投稿をご覧ください。

ファクトリパターンと抽象ファクトリパターンの基本的な違いは何ですか?

デザインパターン:ファクトリvsファクトリメソッドvsアブストラクトファクトリ

于 2016-05-15T08:09:18.893 に答える
3

動機の違いを理解する:

オブジェクトを配置し、オブジェクトの相互関係を具体的に実装するツールを構築しているとします。オブジェクトのバリエーションを予測するため、オブジェクトのバリエーションを作成する責任を別のオブジェクト(抽象ファクトリと呼びます)に割り当てることにより、間接参照を作成しました。これらのオブジェクトのバリアントを必要とする将来の拡張を予測するため、この抽象化には大きなメリットがあります。

この考え方のもう1つの興味深い動機は、グループ全体のオブジェクトのすべてまたはまったくが対応するバリアントを持たない場合です。いくつかの条件に基づいて、いずれかのバリアントが使用され、いずれの場合もすべてのオブジェクトが同じバリアントである必要があります。オブジェクトのバリアントが共通の統一されたコントラクト(広義のインターフェイス)に従っている限り、具体的な実装コードが壊れることはないはずだと私たちがよく考えるので、これは少し直感的に理解できないかもしれません。ここでの興味深い事実は、特に期待される動作をプログラミングコントラクトでモデル化できない場合は、必ずしもこれが当てはまるとは限らないということです。

単純な(GoFからアイデアを借りた)のは、MS、Mac、またはFedoraOSのルックアンフィールをエミュレートする仮想モニターを言うGUIアプリケーションです。ここで、たとえば、ウィンドウ、ボタンなどのすべてのウィジェットオブジェクトに、MACバリアントから派生したスクロールバーを除くMSバリアントがある場合、ツールの目的はひどく失敗します。

これらの上記のケースは、AbstractFactoryPatternの基本的な必要性を形成します。

一方、多くの人がフレームワークを使用してさまざまなツール(上記の例のような)を構築できるようにフレームワークを作成していると想像してください。フレームワークのアイデアそのものによって、ロジックで具体的なオブジェクトを使用することはできませんが、その必要はありません。むしろ、さまざまなオブジェクトとそれらがどのように相互作用するかの間でいくつかの高レベルの契約を結びます。あなた(フレームワーク開発者として)は非常に抽象的なレベルにとどまっていますが、ツールの各ビルダーはあなたのフレームワーク構成に従うことを余儀なくされています。ただし、彼ら(ツールビルダー)は、構築するオブジェクトと、作成するすべてのオブジェクトがどのように相互作用するかを自由に決定できます。前のケース( Abstract Factory Patternの)とは異なり、あなた(フレームワーク作成者として))この場合、具象オブジェクトを操作する必要はありません。むしろ、オブジェクトのコントラクトレベルにとどまることができます。さらに、前の動機の2番目の部分とは異なり、あなたやツールビルダーは、バリアントからオブジェクトを混合する状況に陥ることはありません。ここでは、フレームワークコードはコントラクトレベルのままですが、すべてのツールビルダーは(ケース自体の性質により)独自のオブジェクトの使用に制限されています。この場合のオブジェクトの作成は各実装者に委任され、フレームワークプロバイダーはオブジェクトを作成して返すための統一されたメソッドを提供するだけです。このようなメソッドは、フレームワーク開発者がコードを進めるために避けられず、ファクトリメソッド基になるパターンのファクトリメソッドパターン)と呼ばれる特別な名前が付いています。

いくつかのメモ:

  • 「テンプレートメソッド」に精通している場合は、任意の形式のフレームワークに関連するプログラムの場合、ファクトリメソッドがテンプレートメソッドから呼び出されることがよくあります。対照的に、アプリケーションプログラムのテンプレートメソッドは、多くの場合、特定のアルゴリズムの単純な実装であり、ファクトリメソッドはありません。
  • さらに、考えを完全にするために、フレームワーク(上記)を使用して、ツールビルダーが各ファクトリメソッド内でツールを構築するときに、具体的なオブジェクトを作成する代わりに、彼/彼女はさらに責任を抽象に委任することができます-ファクトリオブジェクト。ツールビルダーが将来の拡張のために具体的なオブジェクトのバリエーションを予測する場合に提供されます。

サンプルコード:

//Part of framework-code
BoardGame {
    Board createBoard() //factory method. Default implementation can be provided as well
    Piece createPiece() //factory method

    startGame(){        //template method
         Board borad = createBoard()
         Piece piece = createPiece()
         initState(board, piece)
    }
}


//Part of Tool-builder code
Ludo inherits  BoardGame {
     Board createBoard(){ //overriding of factory method
         //Option A: return new LudoBoard() //Lodu knows object creation
         //Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
     }
….
}

//Part of Tool-builder code
Chess inherits  BoardGame {
    Board createBoard(){ //overriding of factory method
        //return a Chess board
    }
    ….
}
于 2016-09-22T10:54:43.150 に答える
2

クラスAはインターフェイスBでプログラムされているため、本番コードではほとんどの場合、抽象ファクトリパターンを使用します。また、AはBのインスタンスを作成する必要があります。したがって、AはBのインスタンスを生成するためのファクトリオブジェクトを持っている必要があります。 。したがって、AはBの具体的なインスタンスに依存していません。それが役立つことを願っています。

于 2015-07-16T08:42:15.093 に答える
2

そこにはかなりの数の定義があります。基本的に、ファクトリパターンを記述する3つの一般的な方法は次のとおりです。

  1. シンプルファクトリー

条件に基づく単純なオブジェクト作成メソッド/クラス。

  1. ファクトリメソッド

実装を提供するためにサブクラスを使用するファクトリメソッドデザインパターン。

  1. 抽象ファクトリ

抽象ファクトリデザインパターンは、具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリを生成します。

以下のリンクは非常に役に立ちました-工場比較-refactoring.guru

于 2021-02-19T16:13:50.940 に答える
1

最小限のインターフェースで非常にシンプルにするには、「//1」にフォーカスしてください。

class FactoryProgram
    {
        static void Main()
        {
            object myType = Program.MyFactory("byte");
            Console.WriteLine(myType.GetType().Name);

            myType = Program.MyFactory("float"); //3
            Console.WriteLine(myType.GetType().Name);

            Console.ReadKey();
        }

        static object MyFactory(string typeName)
        {
            object desiredType = null; //1
            switch (typeName)
            {
                case "byte": desiredType = new System.Byte(); break; //2
                case "long": desiredType = new System.Int64(); break;
                case "float": desiredType = new System.Single(); break;
                default: throw new System.NotImplementedException();
            }
            return desiredType;
        }
    }

ここで重要なポイント:1。FactoryおよびAbstractFactoryメカニズムは継承を使用する必要があります(System.Object-> byte、float ...); したがって、プログラムに継承がある場合、Factory(Abstract Factoryはおそらく存在しないでしょう)はすでに設計2に存在します。作成者(MyFactory)は具象型を知っているので、具象型オブジェクトをcaller(Main)に返します。抽象ファクトリでは、リターンタイプはインターフェイスになります。

interface IVehicle { string VehicleName { get; set; } }
interface IVehicleFactory
    {
        IVehicle CreateSingleVehicle(string vehicleType);
    }
class HondaFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports": return new SportsBike();
                case "Regular":return new RegularBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }
class HeroFactory : IVehicleFactory
    {
        public IVehicle CreateSingleVehicle(string vehicleType)
        {
            switch (vehicleType)
            {
                case "Sports":  return new SportsBike();
                case "Scooty": return new Scooty();
                case "DarkHorse":return new DarkHorseBike();
                default: throw new ApplicationException(string.Format("Vehicle '{0}' cannot be created", vehicleType));
            }
        }
    }

class RegularBike : IVehicle { public string VehicleName { get { return "Regular Bike- Name"; } set { VehicleName = value; } } }
class SportsBike : IVehicle { public string VehicleName { get { return "Sports Bike- Name"; } set { VehicleName = value; } } }
class RegularScooter : IVehicle { public string VehicleName { get { return "Regular Scooter- Name"; } set { VehicleName = value; } } }
class Scooty : IVehicle { public string VehicleName { get { return "Scooty- Name"; } set { VehicleName = value; } } }
class DarkHorseBike : IVehicle { public string VehicleName { get { return "DarkHorse Bike- Name"; } set { VehicleName = value; } } }

class Program
{
    static void Main(string[] args)
    {
        IVehicleFactory honda = new HondaFactory(); //1
        RegularBike hondaRegularBike = (RegularBike)honda.CreateSingleVehicle("Regular"); //2
        SportsBike hondaSportsBike = (SportsBike)honda.CreateSingleVehicle("Sports");
        Console.WriteLine("******* Honda **********"+hondaRegularBike.VehicleName+ hondaSportsBike.VehicleName);

        IVehicleFactory hero = new HeroFactory();
        DarkHorseBike heroDarkHorseBike = (DarkHorseBike)hero.CreateSingleVehicle("DarkHorse");
        SportsBike heroSportsBike = (SportsBike)hero.CreateSingleVehicle("Sports");
        Scooty heroScooty = (Scooty)hero.CreateSingleVehicle("Scooty");
        Console.WriteLine("******* Hero **********"+heroDarkHorseBike.VehicleName + heroScooty.VehicleName+ heroSportsBike.VehicleName);

        Console.ReadKey();
    }
}

重要なポイント:1。要件:ホンダは「レギュラー」、「スポーツ」を作成しますが、ヒーローは「ダークホース」、「スポーツ」、「スクーティー」を作成します。2.なぜ2つのインターフェースなのか?1つはメーカータイプ(IVehicleFactory)用で、もう1つは製品ファクトリー(IVehicle)用です。2つのインターフェイスを理解するもう1つの方法は、抽象ファクトリは関連するオブジェクトを作成することです。2.キャッチは、IVehicleFactoryの子が戻り、IVehicle(ファクトリのコンクリートではなく)です。だから私は親変数(IVehicle);を取得します。次に、CreateSingleVehicleを呼び出して、親オブジェクトを実際の子オブジェクトにキャストすることにより、実際の具象型を作成します。私がそうしたらどうなるでしょうRegularBike heroRegularBike = (RegularBike)hero.CreateSingleVehicle("Regular");; ApplicationExceptionが発生するため、必要に応じて説明する汎用抽象ファクトリが必要です。

于 2017-09-07T11:12:18.733 に答える
1

ファクトリデザインパターン

generation 1 <- generation 2 <- generation 3
//example
(generation 1) shape <- (generation 2) rectangle, oval <- (generation 3) rectangle impressionism, rectangle surrealism, oval impressionism, oval surrealism

工場

ユースケース:1つのオブジェクトをインスタンス化するgeneration 2

シンプルな場所で作れるCreational柄です。generation 2SRPおよびOCPに準拠しています。すべての変更は単一のクラスで行われます。

enum ShapeType {
    RECTANGLE,
    OVAL
}

class Shape {}

//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//Factory
class Factory {
    Shape createShape(ShapeType type) {

        switch (type) {
            case RECTANGLE:
                return new Rectangle();
            case OVAL:
                return new Oval();
        }
    }
}

//Creator
class Painter {

    private Factory factory;

    Painter(Factory factory) {
        this.factory = factory;
    }

    Shape prepareShape(ShapeType type) {
        return factory.createShape(type);
    }
}

//using
class Main {
    void main() {
        Painter painter = new Painter(new Factory());

        Shape shape1 = painter.prepareShape(ShapeType.RECTANGLE);
        Shape shape2 = painter.prepareShape(ShapeType.OVAL);
    }
}

ファクトリメソッド

ユースケース:1つのオブジェクトをインスタンス化するgeneration 3

次世代の家族との協力を支援します。すべての画家は印象派、シュルレアリスムのような独自のスタイルを持っています...ファクトリーとしてFactory Method抽象を使用します(抽象メソッド)そしてこのメ​​ソッドの実現ですCreatorConcrete Creators

enum ShapeType {
    RECTANGLE,
    OVAL
}

class Shape {}

//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}

//Creator
abstract class Painter {

    Shape prepareShape(ShapeType type) {
        return createShape(type);
    }

    //Factory method
    abstract Shape createShape(ShapeType type);
}

//Concrete Creators
class PainterImpressionism {

    @override
    Shape createShape(ShapeType type) {
        switch (type) {
            case RECTANGLE:
                return new RectangleImpressionism();
            case OVAL:
                return new OvalImpressionism();
        }
    }
}

class PainterSurrealism {

    @override
    Shape createShape(ShapeType type) {
        switch (type) {
            case RECTANGLE:
                return new RectangleSurrealism();
            case OVAL:
                return new OvalSurrealism();
        }
    }
}

//using
class Main {
    void main() {
        Painter painterImpressionism = new PainterImpressionism();
        Shape shape1 = painterImpressionism.prepareShape(ShapeType.RECTANGLE);

        Painter painterSurrealism = new PainterSurrealism();
        Shape shape2 = painterSurrealism.prepareShape(ShapeType.RECTANGLE);
    }
}

抽象ファクトリ

ユースケース:のすべてのオブジェクトをインスタンス化しますgeneration 3

Factoryの抽象化Factoryと実現の一部ですConcrete Factories


//Concrete Products
//generation 2
class Rectangle extends Shape {}
class Oval extends Shape {}

//generation 3
class RectangleImpressionism extends Rectangle {}
class OvalImpressionism extends Oval {}
class RectangleSurrealism extends Rectangle {}
class OvalSurrealism extends Oval {}

//Abstract Factory
interface Factory {
    Rectangle createRectangle();
    Oval createOval();
}

//Concrete Factories
class ImpressionismFactory implements Factory {
    @Override
    public Rectangle createRectangle() {
        return new RectangleImpressionism();
    }

    @Override
    public Oval createOval() {
        return new OvalImpressionism();
    }
}

class SurrealismFactory implements Factory {
    @Override
    public Rectangle createRectangle() {
        return new RectangleSurrealism();
    }

    @Override
    public Oval createOval() {
        return new OvalSurrealism();
    }
}

//Creator
class Painter {

    Rectangle rectangle;
    Oval oval;

    Painter(Factory factory) {
        rectangle = factory.createRectangle();
        rectangle.resize();

        oval = factory.createOval();
        oval.resize();
    }
}

//using
class Main {
    void main() {
        Painter painter1 = new Painter(new ImpressionismFactory());
        Shape shape1 = painter1.rectangle;
        Shape shape2 = painter1.oval;

        Painter painter2 = new Painter(new ImpressionismFactory());
        Shape shape3 = painter2.rectangle;
        Shape shape4 = painter1.oval;
    }
}
于 2021-03-08T19:44:39.977 に答える
1

A)ファクトリメソッドパターン

ファクトリメソッドは、オブジェクトを作成するためのインターフェイスを提供するが、サブクラスが作成されるオブジェクトのタイプを変更できるようにする作成デザインパターンです。

基本クラスとそれを拡張するサブクラスに作成メソッドがある場合は、ファクトリメソッドを調べている可能性があります。

B)抽象ファクトリパターン

抽象ファクトリは、具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリを生成できるようにする創造的なデザインパターンです。

「オブジェクトのファミリ」とは何ですか?たとえば、次のクラスのセットを取り上げます:トランスポート+エンジン+コントロール。これらにはいくつかのバリエーションがあります。

1-車+CombustionEngine+ SteeringWheel

2-プレーン+JetEngine+ヨーク

プログラムが製品ファミリで動作しない場合は、抽象ファクトリは必要ありません。

また、多くの人が抽象ファクトリパターンと抽象として宣言された単純なファクトリクラスを混同しています。そうしないでください!

REF:https ://refactoring.guru/design-patterns/factory-comparison

于 2021-09-11T16:13:02.140 に答える
1

私の推定では、@ TomDallingによって与えられた答えは確かに正しいです(それが価値があるものについて)が、コメントにはまだ多くの混乱があるようです。

ここで私が行ったことは、2つのパターンの少し変わった例をいくつか作成し、それらを一見非常によく似たものに見せようとしたことです。これは、それらを分離する重要な違いを特定するのに役立ちます。

ファクトリメソッド 抽象ファクトリ

パターンに完全に慣れていない場合、これらの例はおそらく開始するのに最適な場所ではありません。

ファクトリメソッド

ここに画像の説明を入力してください

Client.javaish

Client(Creator creator) {
    ProductA a = creator.createProductA();
}

Creator.javaish

Creator() {}

void creatorStuff() {
    ProductA a = createProductA();
    a.doSomething();
    ProductB b = createProductB();
    b.doStuff();
}

abstract ProductA createProductA();

ProductB createProductB() {
    return new ProductB1();
}

なぜとがありCreatorますClientか?

なぜだめですか?はFactoryMethod両方で使用できますが、Creator作成される特定の製品を決定するのはそのタイプになります。

なぜcreateProductB抽象化されないのCreatorですか?

デフォルトの実装を提供できますが、サブクラスはメソッドをオーバーライドして独自の実装を提供できます。

ファクトリメソッドは1つの製品しか作成しないと思いましたか?

各メソッドは1つの製品のみを返しますが、作成者は複数のファクトリメソッドを使用できます。これらは、必ずしも特定の方法で関連付けられているわけではありません。

抽象ファクトリ

ここに画像の説明を入力してください

Client.javaish

AbstractFactory factory;

Client() {
    if (MONDAY) {
        factory = new Factory2();
    } else {
        factory = new AbstractFactory();
    }
}

void clientStuff() {
    ProductA a = factory.createProductA();
    a.doSomething();
    ProductB b = factory.createProductB();
    b.doStuff();
}

待って!あなたAbstractFactoryはそうではありません、まあ...

それは大丈夫です、私たちはまだインターフェースを提供しています。createメソッドのreturnタイプは、作成したい製品のスーパータイプです。

聖なる煙バットマン!Factory2オーバーライドしませんcreateProductA()、「製品のファミリ」はどうなりましたか?

パターンには、オブジェクトが複数のファミリに属する​​ことはできないということは何もありません(ただし、ユースケースで禁止されている場合があります)。各コンクリート工場は、どの製品を一緒に作成できるかを決定する責任があります。

それは正しくありえません、Client依存性注入を使用していません

具体的なクラスをどこかに配置するかどうかを決定する必要がありますが、Clientそれでもインターフェイスに書き込まれAbstractFactoryます。

ここでの混乱は、人々が依存性注入と構成を混同していることです。HAS-Aは、どのように入手したかに関係なく。IS-A関係とは対照的であり、それらの間に継承はありません。ClientAbstractFactoryClientAbstractFactory

主な違い

  • 抽象ファクトリは常にオブジェクトのファミリに関するものです
  • ファクトリメソッドは、サブクラスが具象オブジェクトのタイプを指定できるようにする単なるメソッドです。
  • 抽象ファクトリはクライアントへのインターフェイスを提供し、製品が使用される場所とは別のものです。ファクトリメソッドは、作成者自身が使用することも、クライアントに公開することもできます。

概要

ファクトリの目的は、クライアントまたはそれ自体のいずれかにオブジェクトを提供することです。

作成者には独自の責任があり、オブジェクトを使用するか、クライアントに渡す必要がある場合があります

オブジェクトを作成するためのインターフェースを定義しますが、インスタンス化するクラスをサブクラスに決定させます。ファクトリメソッドを使用すると、クラスはインスタンス化をサブクラスに延期できます。-GoF

抽象ファクトリのみ:

具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリーを作成するためのインターフェースを提供します。-GoF


ダイアグラムで遊びたい場合は、PlantUMLコード:

@startuml FactoryMethod
abstract class Creator {
    creatorStuff()
    {abstract} createProductA(): ProductA
    createProductB(): ProductB
}
class Creator1 {
    createProductA(): ProductA
}
class Creator2 {
    createProductA(): ProductA
    createProductB(): ProductB
}

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
    ' class Product1B
}
together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}
Client --> Creator

Creator <|-- Creator1
Creator <|-- Creator2

Creator --> ProductB1
ProductA1 <-- Creator1
ProductA1 <-- Creator2
ProductB2 <-- Creator2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

ProductA <- Creator

@enduml
@startuml AbstractFactory

together {
    interface ProductA {
        doSomething()
    }
    class ProductA1
}

together {
    interface ProductB {
        doStuff()
    }
    class ProductB1
    class ProductB2
}

class AbstractFactory {
    createProductA(): ProductA
    createProductB(): ProductB
    --
    -
}

class Factory2 {
    createProductB(): ProductB
}

Client --> AbstractFactory
AbstractFactory <|-- Factory2

ProductA <|.. ProductA1
ProductB <|.. ProductB1
ProductB <|.. ProductB2

AbstractFactory --> ProductA1
AbstractFactory --> ProductB1
ProductB2 <-- Factory2

@enduml
于 2021-10-22T13:20:28.507 に答える
0

いつでもファクトリメソッドよりもアブストラクトファクトリを好みます。上記のTomDallingの例(すばらしい説明)から、Abstract Factoryの方が、別のFactoryをコンストラクターに渡すだけで構成可能であることがわかります(ここで使用されているコンストラクターの依存性注入)。ただし、ファクトリメソッドでは、新しいクラス(管理するものが多い)を導入し、サブクラス化を使用する必要があります。継承よりも常に構成を優先します。

于 2016-08-30T04:33:46.243 に答える
0

抽象ファクトリ:ファクトリのファクトリ。具体的なクラスを指定せずに、個々の関連/依存する工場をグループ化する工場。 抽象ファクトリの例

ファクトリ:インスタンス化ロジックを子クラスに委任する方法を提供します。 ファクトリパターンの例

于 2019-05-06T05:54:16.450 に答える
-1
于 2018-05-04T18:22:57.943 に答える
-1

以前の回答の多くは、抽象ファクトリとファクトリメソッドパターン間のコード比較を提供していません。以下は、Javaを介してそれを説明する私の試みです。簡単な説明が必要な人のお役に立てば幸いです。

GoFが適切に言うように、Abstract Factoryは、具体的なクラスを指定せずに、関連オブジェクトまたは依存オブジェクトのファミリーを作成するためのインターフェースを提供します。

public class Client {
    public static void main(String[] args) {
        ZooFactory zooFactory = new HerbivoreZooFactory();
        Animal animal1 = zooFactory.animal1();
        Animal animal2 = zooFactory.animal2();
        animal1.sound();
        animal2.sound();

        System.out.println();

        AnimalFactory animalFactory = new CowAnimalFactory();
        Animal animal = animalFactory.createAnimal();
        animal.sound();
    }
}

public interface Animal {
    public void sound();
}

public class Cow implements Animal {

    @Override
    public void sound() {
        System.out.println("Cow moos");
    }
}

public class Deer implements Animal {

    @Override
    public void sound() {
        System.out.println("Deer grunts");
    }

}

public class Hyena implements Animal {

    @Override
    public void sound() {
        System.out.println("Hyena.java");
    }

}

public class Lion implements Animal {

    @Override
    public void sound() {
        System.out.println("Lion roars");
    }

}

public interface ZooFactory {
    Animal animal1();

    Animal animal2();
}

public class CarnivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Lion();
    }

    @Override
    public Animal animal2() {
        return new Hyena();
    }

}

public class HerbivoreZooFactory implements ZooFactory {

    @Override
    public Animal animal1() {
        return new Cow();
    }

    @Override
    public Animal animal2() {
        return new Deer();
    }

}

public interface AnimalFactory {
    public Animal createAnimal();
}

public class CowAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Cow();
    }

}

public class DeerAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Deer();
    }

}

public class HyenaAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Hyena();
    }

}

public class LionAnimalFactory implements AnimalFactory {

    @Override
    public Animal createAnimal() {
        return new Lion();
    }

}
于 2018-06-09T06:11:02.450 に答える
-1

リアルタイムの例を使用した抽象ファクトリデザインパターン:抽象ファクトリデザインパターンとは何ですか?これは、ファクトリメソッドのデザインパターンに似ています。複数の工場がある場合は、このパターンを使用する必要があります。このパターンで定義された工場のグループがあります。ファクトリメソッドパターンは、抽象的なファクトリデザインパターンのサブセットです。それらには、ファクトリパターンと同じ利点があります。抽象ファクトリはオブジェクト構成に依存しますが、ファクトリメソッドは継承を扱います。リアルタイムの例を使用したJavaのファクトリデザインパターン:ファクトリデザインパターンとは何ですか?これは主にオブジェクト指向プログラミングで使用される設計です。それは創造的なパターンの1つです。インスタンスの作成がすべてです。クライアントは、オブジェクト作成ロジックにさらされることなくオブジェクトを作成します。さまざまなフレームワークで広く使用されています。例:Springフレームワーク。このパターンは、クラスが作成する必要のある別のオブジェクトを認識していない場合に使用します。リアルタイムの例:私たちの車が道路で故障したとき。修理担当者が修理のための工具を携帯できるように、使用している車両の種類を修理担当者に通知する必要があります。私たちの入力に従って、修理工は問題を修正し、私たちが再び旅行する準備をします。これらのパターンを使用する組み込みメソッドがいくつかあります。JavaUtilcalendarクラスのgetInstance()メソッドの例。getInstance()を使用すると、このメソッドを実行するたびにオブジェクトを取得できます。Javautilcalendar:getInstance()はメソッドreturnオブジェクトです。修理担当者が修理のための工具を携帯できるように、使用している車両の種類を修理担当者に通知する必要があります。私たちの入力に従って、修理工は問題を修正し、私たちが再び旅行する準備をします。これらのパターンを使用する組み込みメソッドがいくつかあります。JavaUtilcalendarクラスのgetInstance()メソッドの例。getInstance()を使用すると、このメソッドを実行するたびにオブジェクトを取得できます。Javautilcalendar:getInstance()はメソッドreturnオブジェクトです。修理担当者が修理のための工具を携帯できるように、使用している車両の種類を修理担当者に通知する必要があります。私たちの入力に従って、修理工は問題を修正し、私たちが再び旅行する準備をします。これらのパターンを使用する組み込みメソッドがいくつかあります。JavaUtilcalendarクラスのgetInstance()メソッドの例。getInstance()を使用すると、このメソッドを実行するたびにオブジェクトを取得できます。Javautilcalendar:getInstance()はメソッドreturnオブジェクトです。 https://trendydevx.com/factory-design-pattern-in-java-with-realtime-example/

于 2020-10-29T18:32:54.597 に答える
-1

私の結論:違いはありません。なんで?工場以外のオブジェクトにファクトリメソッドを装備する理由がわからないためです。そうしないと、責任の分離の原則に違反することになります。さらに、単一のファクトリメソッドを持つファクトリと複数のファクトリメソッドを持つファクトリの違いはわかりません。どちらも、単一のファミリメンバーのファミリがファミリではないことを誰かが証明できない限り、「関連オブジェクトのファミリ」を作成します。または、単一のアイテムを含むコレクションはコレクションではありません。

于 2022-02-07T04:10:11.490 に答える