C++深入浅出工場モード(初識編)


初識工場モデル
まず工場モデルの紹介を見てみましょう
このタイプの設計モードは、オブジェクトを作成するための最適な方法を提供する作成モードに属します.
ファクトリモードでは、オブジェクトを作成するときにクライアントに作成ロジックを露出させず、共通のインタフェースを使用して新しく作成したオブジェクトを指します.
簡単に言えば、C++マルチステートのプロパティを使用すると、継承関係のあるクラスが、対応するサブクラス(派生クラス)オブジェクトをファクトリクラスで作成します.プロジェクトが複雑な場合、サブクラスオブジェクトの作成を容易にできます.
工場モードの実現方式はそれぞれ簡単な工場モード、工場方法モード、抽象工場モードであり、各実現方式には優劣がある.
最近靴を炒めるのはとても火がついて、それでは靴工場の形式で、一つ一つ分析して各実現方式に対して分析を行います.
単純ファクトリモード
具体的な状況:
  • 靴工場はナイキ、アディダス、李寧ブランドの靴の生産を指定することができる.どの靴が人気があるか、ボスはどれを生産して、情勢を見て生産します.

  • UML図:
    単純工場モデルの構造構成:
  • ファクトリクラス(ShoesFactory):ファクトリモードのコアクラスで、指定したインスタンスオブジェクトを作成するためのインタフェースが定義されます.
  • 抽象プロダクトクラス(Shoes):特定のプロダクトクラスの継承の親または実装のインタフェースです.
  • 特定のプロダクトクラス(NiKeShoes\AdidasShoes\LiNingShoes):この特定のプロダクトインスタンスは、ファクトリクラスによって作成されたオブジェクトです.

  • 単純工場モデルの特徴:
  • ファクトリクラスには、特定のプロダクトオブジェクトを作成する関数がカプセル化されています.

  • 単純な工場モデルの欠陥:
  • は拡張性が非常に悪く、新製品を追加する場合は、工場クラスを修正する必要があります.

  • 単純ファクトリモードのコード:
  • Shoesは靴の抽象クラス(ベースクラス)であり、インタフェース関数はShow()であり、靴広告を表示するために使用される.
  • NiKeShoesAdidasShoesLiNingShoesは具体的な靴の種類であり、それぞれナイキ、アディダス、李寧靴ブランドの靴であり、それらはShoes抽象類に継承されている.
  • //      
    class Shoes
    {
    public:
        virtual ~Shoes() {}
        virtual void Show() = 0;
    };
    
    //     
    class NiKeShoes : public Shoes
    {
    public:
        void Show()
        {
            std::cout << "      ,     :Just do it" << std::endl;
        }
    };
    
    //       
    class AdidasShoes : public Shoes
    {
    public:
        void Show()
        {
            std::cout << "        ,     :Impossible is nothing" << std::endl;
        }
    };
    
    //     
    class LiNingShoes : public Shoes
    {
    public:
        void Show()
        {
            std::cout << "      ,     :Everything is possible" << std::endl;
        }
    };
  • ShoesFactoryは工場クラスであり、クラスには靴タイプに応じて靴製品オブジェクトに対応するCreateShoes(SHOES_TYPE type)関数が作成される.
  • enum SHOES_TYPE
    {
        NIKE,
        LINING,
        ADIDAS
    };
    
    //    
    class ShoesFactory
    {
    public:
        //                
        Shoes *CreateShoes(SHOES_TYPE type)
        {
            switch (type)
            {
            case NIKE:
                return new NiKeShoes();
                break;
            case LINING:
                return new LiNingShoes();
                break;
            case ADIDAS:
                return new AdidasShoes();
                break;
            default:
                return NULL;
                break;
            }
        }
    };
  • main関数は、工場オブジェクトを構築した後、指定されたタイプの特定の靴製品オブジェクトを作成し、特定の靴製品オブジェクトを作成すると、広告を直接印刷することができます.new方式でオブジェクトを作成したので、使い切ったらdeleteでリソースを解放しますよ!
  • int main()
    {
        //       
        ShoesFactory shoesFactory;
    
        //                
        Shoes *pNikeShoes = shoesFactory.CreateShoes(NIKE);
        if (pNikeShoes != NULL)
        {
            //         
            pNikeShoes->Show();
    
            //     
            delete pNikeShoes;
            pNikeShoes = NULL;
        }
    
        //                
        Shoes *pLiNingShoes = shoesFactory.CreateShoes(LINING);
        if (pLiNingShoes != NULL)
        {
            //         
            pLiNingShoes->Show();
    
            //     
            delete pLiNingShoes;
            pLiNingShoes = NULL;
        }
    
        //                
        Shoes *pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
        if (pAdidasShoes != NULL)
        {
            //           
            pAdidasShoes->Show();
    
            //     
            delete pAdidasShoes;
            pAdidasShoes = NULL;
        }
    
        return 0;
    }
  • 出力結果:
  • [root@lincoding factory]# ./simpleFactory 
          ,     :Just do it
            ,     :Impossible is nothing
          ,     :Everything is possible

    ファクトリメソッドモード
    具体的な状況:
  • 現在、各種類の靴は非常に熱いので、各タイプの靴を大量に生産するために、異なるブランドの靴に対して独立した生産ラインを開設しなければならない.そうすれば、各生産ラインは同じタイプのブランドの靴しか生産できない.

  • UML図:
    工場メソッドモデルの構造構成:
  • 抽象工場類工場(ShoesFactory):工場方法モデルの核心類、具体的な製品を作成するインタフェースを提供し、具体的な工場類によって実現される.
  • 特定工場クラス(NiKeProducer\AdidasProducer\LiNingProducer):抽象工場に継承され、対応する特定製品オブジェクトの作成方法を実現する.
  • 抽象プロダクトクラス(Shoes):特定のプロダクトが継承する親(ベースクラス).
  • 特定の製品クラス(NiKeShoes\AdidasShoes\LiNingShoes):特定の工場で作成されたオブジェクトです.
  • 工場方法モデルの特徴:
  • ファクトリメソッドモデルはファクトリクラスを抽象化し、具体的な製品を作成するインタフェースを提供し、サブクラスに渡して実現する.
  • ファクトリメソッドモードの応用は、特定のプロダクトオブジェクトの作成をカプセル化するためだけでなく、特定のプロダクトオブジェクトの作成を特定のファクトリクラスに配置して実装する.

  • 工場方法モデルの欠陥:
  • 製品を追加するたびに、対応する製品の具体的な工場クラスを追加する必要があります.単純なファクトリ・モードに比べて、ファクトリ・メソッド・モードにはより多くのクラス定義が必要です.
  • 生産ラインには1つの製品しかありません.

  • ファクトリメソッドモードのコード:
  • ShoesFactory抽象工場クラスは、特定の靴製品を作成する純粋な虚関数を提供します.
  • NiKeProducerAdidasProducerLiNingProducer具体的な工場類は、持続的な工場類を継承し、具体的な靴製品オブジェクトの作成を実現する.
  • //    
    class ShoesFactory
    {
    public:
        virtual Shoes *CreateShoes() = 0;
        virtual ~ShoesFactory() {}
    };
    
    //      /   
    class NiKeProducer : public ShoesFactory
    {
    public:
        Shoes *CreateShoes()
        {
            return new NiKeShoes();
        }
    };
    
    //        /   
    class AdidasProducer : public ShoesFactory
    {
    public:
        Shoes *CreateShoes()
        {
            return new AdidasShoes();
        }
    };
    
    //      /   
    class LiNingProducer : public ShoesFactory
    {
    public:
        Shoes *CreateShoes()
        {
            return new LiNingShoes();
        }
    };
    
  • main関数は、各タイプの靴について、各タイプの生産ラインを構築し、各生産ラインから対応する靴を生産する.特定の工場オブジェクトと特定の製品オブジェクトは、使用済みになったらdeleteを通じてリソースを解放する必要があることに注意してください.
  • int main()
    {
        // ================        ==================== //
        //          
        ShoesFactory *niKeProducer = new NiKeProducer();
        //          
        Shoes *nikeShoes = niKeProducer->CreateShoes();
        //         
        nikeShoes->Show();
        //     
        delete nikeShoes;
        delete niKeProducer;
    
        // ================          ==================== //
        //            
        ShoesFactory *adidasProducer = new AdidasProducer();
        //            
        Shoes *adidasShoes = adidasProducer->CreateShoes();
        //          
        adidasShoes->Show();
        //     
        delete adidasShoes;
        delete adidasProducer;
    
        return 0;
    }
  • 出力結果:
  • [root@lincoding factory]# ./methodFactory 
          ,     :Just do it
            ,     :Impossible is nothing

    抽象ファクトリモード
    具体的な状況:
  • 靴工場は業務拡大のため、靴だけでなくスポーツブランドの服も一緒に生産した.

  • UML図:
    抽象ファクトリ・モードの構造構成(ファクトリ・メソッド・モードと同様):
  • 抽象工場類工場(ShoesFactory):工場方法モデルの核心類、具体的な製品を作成するインタフェースを提供し、具体的な工場類によって実現される.
  • 特定工場クラス(NiKeProducer):抽象工場に継承され、対応する特定製品オブジェクトの作成方法を実現する.
  • 抽象プロダクトクラス(Shoes\Clothe):特定のプロダクトが継承する親(ベースクラス).
  • 特定の製品クラス(NiKeShoes\NiKeClothe):特定の工場で作成されたオブジェクトです.
  • 抽象工場モデルの特徴:
  • は、複数のプロダクトファミリー内のプロダクトオブジェクトを作成できるインタフェースを提供します.ナイキ工場を設立すれば、ナイキ靴製品、衣類製品、ズボン製品などを作成することができます.

  • 抽象工場モデルの欠陥:
  • 工場メソッドモデルと同様に、製品を追加する場合は、対応する製品の具体的な工場クラスを追加する必要があります.

  • 抽象工場触是のコード:
  • ClotheShoesは、それぞれ服と靴の抽象製品類である.
  • NiKeClotheNiKeShoesは、それぞれナイキ服とナイキ服の具体的な製品類である.
  • //      
    class Clothe
    {
    public:
        virtual void Show() = 0;
        virtual ~Clothe() {}
    };
    
    //     
    class NiKeClothe : public Clothe
    {
    public:
        void Show()
        {
            std::cout << "      ,      !" << std::endl;
        }
    };
    
    //      
    class Shoes
    {
    public:
        virtual void Show() = 0;
        virtual ~Shoes() {}
    };
    
    //     
    class NiKeShoes : public Shoes
    {
    public:
        void Show()
        {
            std::cout << "      ,     !" << std::endl;
        }
    };
  • Factoryは抽象的な工場であり、靴CreateShoes()と衣類製品CreateClothe()のオブジェクトを作成するインタフェースを提供する.
  • NiKeProducerは具体的な工場であり、ナイキの靴とナイキの服を作成する方法を実現した.
  • //   
    class Factory
    {
    public:
        virtual Shoes *CreateShoes() = 0;
        virtual Clothe *CreateClothe() = 0;
        virtual ~Factory() {}
    };
    
    //      /   
    class NiKeProducer : public Factory
    {
    public:
        Shoes *CreateShoes()
        {
            return new NiKeShoes();
        }
        
        Clothe *CreateClothe()
        {
            return new NiKeClothe();
        }
    };
  • main関数は、ナイキファクトリオブジェクトを構築し、ナイキファクトリオブジェクトを介してナイキ製品ファミリーの衣類および靴オブジェクトを再作成します.同様に、オブジェクトが使用されなくなった場合は、手動でリソースを解放する必要があります.
  • int main()
    {
        // ================        ==================== //
        //          
        Factory *niKeProducer = new NiKeProducer();
        
        //          
        Shoes *nikeShoes = niKeProducer->CreateShoes();
        //          
        Clothe *nikeClothe = niKeProducer->CreateClothe();
        
        //         
        nikeShoes->Show();
        //         
        nikeClothe->Show();
        
        //     
        delete nikeShoes;
        delete nikeClothe;
        delete niKeProducer;
    
    
        return 0;
    }
  • 出力結果:
  • [root@lincoding factory]# ./abstractFactory 
          ,     !
          ,      !

    まとめ
    以上の3つの工場モデルは、製品を追加する際に、一定の欠陥がある.
  • 単純工場モデルは、工場類を修正する必要があり、開閉法則に反している.
  • ファクトリモードと抽象ファクトリモードは、対応する製品の具体的なファクトリクラスを追加する必要があり、コードの作成量を増大させる.

  • では、製品を追加する際に、工場類を修正しなくても、具体的な工場類を追加しなくてもいい方法はありませんか.
    筆者は実際のプロジェクトでパッケージング性の非常に強い工場類を見て、新製品を拡張する時、工場類を修正する必要はなく、具体的な工場類を追加する必要もなく、詳細はC++深入浅出工場モード(進級編)にジャンプして読むことができる.