1. ホーム
  2. factory-pattern

[解決済み] Abstract FactoryとFactoryのデザインパターンの違いは何ですか?

2022-03-18 20:24:41

質問

この2つのパターンの違いについて、たくさんの書き込みがあるのは知っているのですが、いくつか見つけられないことがあるのです。

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

最後の2つの質問は、多くの場所で目にした、私には理解しがたい1つの引用についてです。

両者の違いの1つは Abstract Factoryパターンでは クラスは オブジェクトのインスタンス化を別のオブジェクトに コンポジションによるものであるのに対し、ファクトリー メソッドパターンは継承を使用し サブクラスが処理することに依存します。 のインスタンスを作成します。

私の理解では、ファクトリーメソッドパターンにはCreatorインターフェースがあり、どのConcreteProductをインスタンス化するかはConcreteCreatorが担当することになると思います。これは、オブジェクトのインスタンス化を処理するために継承を使用するということでしょうか?

さて、この引用文に関して、Abstract Factoryパターンは、具体的にどのようにオブジェクトのインスタンス化の責任をコンポジションによって別のオブジェクトに委ねるのでしょうか。これはどういうことでしょうか?私の目には、Abstract Factoryパターンも継承を使用して構築プロセスを行うように見えますが、私はまだこれらのパターンについて学んでいるところです。

特に最後の質問について、何か手助けがあれば、とてもありがたいです。

解決方法は?

両者の違い

ファクトリーメソッドと抽象ファクトリーの主な違いは、ファクトリーメソッドはメソッドであり、抽象ファクトリーはオブジェクトであることです。多くの人がこの2つの言葉を混同し、同じように使い始めているのではないでしょうか。私もこの2つの言葉を学んだとき、何が違うのかを正確に理解するのに苦労したのを覚えています。

ファクトリーメソッドは単なるメソッドなので、サブクラスでオーバーライドすることができます。

<ブロッククオート

ファクトリーメソッドパターンは を継承し、サブクラス を処理するために必要なオブジェクト のインスタンスを作成します。

この引用文は、あるオブジェクトが 自身の ファクトリーメソッドです。したがって、戻り値を変更できるのはサブクラスだけでしょう。

抽象ファクトリーは、そのオブジェクトに複数のファクトリーメソッドを持たせたものです。引用文の前半を見ると

抽象ファクトリーパターンで、クラスは オブジェクトの責任を委ねる を介して別のオブジェクトにインスタンス化する。 コンポジション ...

つまり、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