6

以下は、Abstract Factory パターンを通常表示する方法です。

public abstract class Factory 
{ 
    public abstract Product GetProduct(); 
}

public class ConcreteFactory1 : Factory 
{ 
    public override Product GetProduct() {  return new Product1();  } 
}

class ConcreteFactory2 : Factory 
{
    public override Product GetProduct() { return new Product2(); } 
}

interface Product 
{ 
    void SomeMethod(); 
}

class Product1 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("1"); } 
} 

class Product2 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("2"); } 
}

class Program
{
    static void Main(string[] args)
    {
        Factory f = null;
        Product p = null;
        switch (args[0])
        {
            case "1":
                f = new ConcreteFactory1();
                p = f.GetProduct();
                break;
            case "2":
                f = new ConcreteFactory2();
                p = f.GetProduct();
                break;
        }
        p.SomeMethod();
    }
}

私は通常、次のように書きますが、これは真のパターンではありません。

interface Product 
{ 
    void SomeMethod(); 
}
class Product1 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("1"); } 
} 
class Product2 : Product 
{ 
    public void SomeMethod() { Console.WriteLine("2"); } 
}
public static class Factory 
{ 
    public static Product GetProduct(prodType) 
    {
        Product p = null;
        switch (prodType)
        {
            case "1":
                p = new Product1();
                break;
            case "2":
                p = new Product2();
                break;
        }
        return p;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Product p = Factory.GetProduct(args[0]);
        p.SomeMethod();
    }
}

私の質問は - コンクリート工場の利点は何ですか? 私はその点を理解したことがありません.別の不要なレイヤーを追加しているようです. 2 番目の例は、はるかに簡潔で簡単に見えます。

4

4 に答える 4

8

Odrade は私に同意するので (私はロッカーから完全に外れているわけではないと思います)、これを回答として投稿します。

私が間違っている場合は修正してください。通常、ベースレベルのコードには、使用されるコンクリートファクトリの概念がありません。また、prodType を介して (あなたの場合) 製品タイプを指定することも気にしません。代わりに、具体的なファクトリの実装は、何らかの形式の依存性注入を介して抽象ファクトリに供給され、どのファクトリが使用されているか、または必要な具体的な型についての概念がなくても、コードは楽しく進みます。特に、これらの具体的なファクトリの実装が API のサードパーティ コンシューマによって提供されている場合。

それに関するウィキペディアの記事では、オペレーティング システムの GUI 構築に関する適切な例が提供されています

基本的に、ライブラリ内のコードは、実装の詳細や使用するオペレーティング システムへの依存関係を知らなくても問題なく機能します。あなた (または API のコンシューマー) が Linux に移行する場合 (このウィキペディアの例では)、単純にLinuxFactoryandを実装LinuxButtonして API にフィードします。代わりに、典型的な例のように、列挙などの入力を介して制御する場合、工場は Linux について知る必要があります。

public static class Factory 
{ 
    public static Button GetButton(operatingSystem) 
    {
        switch (operatingSystem)
        {
            case "windows":
                return new WindowsButton();
            case "macintosh":
                return new MacButton();
        }
    }
}

Linux は現在どのように組み込まれていますか? サポートを追加しない限り、それはできません。さらに、API のすべてのコンシューマーは、すべてのオペレーティング システムの実装に間接的に依存しています。

編集:Factory PatternAbstract Factory Patternは 2 つの完全に異なる概念であることに注意してください。そもそもなぜ質問したのかという懸念についてですが、抽象ファクトリパターンは必ずしも必要ではありません。必要がない場合は、複雑さを追加しないでください。単純なファクトリ (2 番目の例はそのバリエーションです) が必要な場合は、それを使用してください。適切な仕事のための適切なツールとそのすべて。

于 2012-06-21T22:16:12.703 に答える
2

私はあなたのアプローチを Factory パターンと呼びます。これは抽象的な Factory とは異なります。

于 2012-06-21T22:17:05.650 に答える
1

コンクリート工場の利点は何ですか? ポイントを理解したことがありません-別の不要なレイヤーを追加しているようです

ファクトリ (一般に、ファクトリ メソッド、抽象ファクトリなど) は、複雑な作成タイプのオブジェクトを解決するために使用されます。異なるタイプの初期化が必要な場合Product1Product2、具象ファクトリにハードコードすることはお勧めできません。

于 2012-06-22T04:16:31.443 に答える
1

「Abstract Factory」は、このパターンの悪い名前です。より良い名前は、GoF も使用した「キット」パターンです。あなたが与えた例では、それは過剰設計であることに同意します。工場が連携して動作する多くのオブジェクトを作成する責任を負っている場合、それはより理にかなっています。次に、それらのさまざまなグループ (場合によってはキット) が、特定の一連の実行時または設計時の条件の下で、さまざまなファクトリによって作成されます。

これはそれについての本当に良い記事です。 メトリックとイングリッシュソケットセットの非ソフトウェアアナロジーは完璧です。

于 2012-06-22T04:46:40.807 に答える