/*****************************************************************//** * \file GoldDir.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef GOLDDIR_H #define GOLDDIR_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "GoldFile.h" using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuCompositePattern { /// <summary> /// 目錄相關類 /// </summary> class GoldDir { public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> GoldDir(string name) :mSname(name) {} public: /// <summary> /// 目錄中可以增加其他文件 /// </summary> /// <param name="pfile"></param> void AddFile(GoldFile* pfile) { mChildFile.push_back(pfile); } /// <summary> /// 目錄中可以增加其他目錄 /// </summary> /// <param name="pdir"></param> void AddDir(GoldDir* pdir) { mChildDir.push_back(pdir); } /// <summary> /// 顯示目錄名,同時也要負責其下面的文件和目錄名的顯示工作 /// </summary> /// <param name="lvlstr"></param> void ShowName(string lvlstr) //lvlstr:爲了顯示層次關係的縮進字符串內容 { //(1)輸出本目錄名 cout << lvlstr << "+" << mSname << endl;//顯示"+"代表是一個目錄,其中會包含其他內容 //(2)輸出所包含的文件名 lvlstr += " "; //本目錄中的文件和目錄的顯示,要縮進一些來顯示 for (auto iter = mChildFile.begin(); iter != mChildFile.end(); ++iter) { (*iter)->ShowName(lvlstr); //顯示文件名 } //(3)輸出所包含的目錄名 for (auto iter = mChildDir.begin(); iter != mChildDir.end(); ++iter) { (*iter)->ShowName(lvlstr); //顯示目錄名,這裏涉及到了遞歸調用 } } private: /// <summary> /// 目錄名 /// </summary> string mSname; /// <summary> /// 目錄中包含的文件列表,記得在源文件上面增加代碼 #include <list> /// </summary> list<GoldFile*> mChildFile; /// <summary> /// 目錄中包含的子目錄列表 /// </summary> list<GoldDir*> mChildDir; }; } #endif /*****************************************************************//** * \file GoldFile.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef GOLDFILE_H #define GOLDFILE_H #include <iostream> #include <sstream> #include <vector> #include <list> using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuCompositePattern { /// <summary> /// 文件相關類 /// </summary> class GoldFile { public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> GoldFile(string name) :mSname(name) {} /// <summary> /// 顯示文件名 /// </summary> /// <param name="lvlstr"></param> void ShowName(string lvlstr) { cout << lvlstr << "-" << mSname << endl; //顯示"-"代表是一個文件,屬末端節點(不會再有子節點) } private: string mSname; //文件名 }; } #endif /*****************************************************************//** * \file PearFile.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef PEARFILE_H #define PEARFILE_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "PearFileSystem.h" using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuPearCompositePattern { /// <summary> /// 文件相關類 /// </summary> class PearFile:public PearFileSystem { public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> PearFile(string name) :mSname(name) {} /// <summary> /// /// </summary> /// <param name="level"></param> void ShowName(int level) { for (int i = 0; i < level; ++i) { cout << " "; } //顯示若干個空格用與對齊 cout << "-" << mSname << endl; } /// <summary> ///添加 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Add(PearFileSystem* pfilesys) { //文件中其實是不可以增加其他文件或者目錄的,所以這裏直接返回-1,無奈的是父類中定義了該接口,所以子類中也必須實現該接口 return -1; } /// <summary> /// 移除 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Remove(PearFileSystem* pfilesys) { //文件中不包含其他文件或者目錄,所以這裏直接返回-1 return -1; } private: /// <summary> /// 文件名 /// </summary> string mSname; }; } #endif /*****************************************************************//** * \file PearDir.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef PEARDIR_H #define PEARDIR_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "PearFileSystem.h" using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuPearCompositePattern { /// <summary> /// 目錄相關類 /// </summary> class PearDir:public PearFileSystem { public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> PearDir(string name) :mSname(name) {} /// <summary> /// 顯示名字 /// </summary> /// <param name="level"></param> void ShowName(int level) { //(1)顯示若干個空格用與對齊 for (int i = 0; i < level; ++i) { cout << " "; } //(2)輸出本目錄名 cout << "+" << mSname << endl; //(3)顯示的層級向下走一級 level++; //(4)輸出所包含的子內容(可能是文件,也可能是子目錄) //遍歷目錄中的文件和子目錄 for (auto iter = mChild.begin(); iter != mChild.end(); ++iter) { (*iter)->ShowName(level); }//end for } /// <summary> /// 增加 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Add(PearFileSystem* pfilesys) { mChild.push_back(pfilesys); return 0; } /// <summary> /// 移除 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Remove(PearFileSystem* pfilesys) { mChild.remove(pfilesys); return 0; } private: /// <summary> /// 文件名 /// </summary> string mSname; /// <summary> /// 目錄中包含的文件或其他目錄列表 /// </summary> list<PearFileSystem*> mChild; // }; } #endif /*****************************************************************//** * \file PearFileSystem.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef PEARFILESYSTEM_H #define PEARFILESYSTEM_H #include <iostream> #include <sstream> #include <vector> #include <list> using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuPearCompositePattern { /// <summary> /// 抽象父類FileSystem(抽象接口) /// </summary> class PearFileSystem { public: /// <summary> /// /// </summary> /// <param name="level"></param> virtual void ShowName(int level) = 0; //顯示名字,參數level用於表示顯示的層級,用於顯示對齊 /// <summary> /// 向當前目錄中增加文件或子目錄 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Add(PearFileSystem* pfilesys) = 0; /// <summary> /// 從當前目錄中移除文件或子目錄 /// </summary> /// <param name="pfilesys"></param> /// <returns></returns> virtual int Remove(PearFileSystem* pfilesys) = 0; /// <summary> /// 做父類時析構函數應該爲虛函數 /// </summary> virtual ~PearFileSystem() {} }; } #endif /*****************************************************************//** * \file JadeFile.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef JADEFILE_H #define JADEFILE_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "JadeFileSystem.h" using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuJadeCompositePattern { /// <summary> /// 文件相關類 /// </summary> class JadeFile :public JadeFileSystem { public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> JadeFile(string name) :mSname(name) {} /// <summary> /// 顯示名字 /// </summary> /// <param name="level"></param> void ShowName(int level) { for (int i = 0; i < level; ++i) { cout << " "; } //顯示若干個空格用與對齊 cout << "-" << mSname << endl; } public: virtual int countNumOfFiles() { return 1; //文件節點,做數量統計時按1計算 } private: /// <summary> /// 文件名 /// </summary> string mSname; }; } #endif /*****************************************************************//** * \file JadeDir.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef JADEDIR_H #define JADEDIR_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "JadeFileSystem.h" using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuJadeCompositePattern { /// <summary> /// /// </summary> class JadeDir:public JadeFileSystem { //該類內容基本沒變,把Add和Remove成員函數前面的virtual修飾符去掉即可。 public: /// <summary> /// 構造函數 /// </summary> /// <param name="name"></param> JadeDir(string name) :mSname(name) {} /// <summary> /// 顯示名字 /// </summary> /// <param name="level"></param> void ShowName(int level) { //(1)顯示若干個空格用與對齊 for (int i = 0; i < level; ++i) { cout << " "; } //(2)輸出本目錄名 cout << "+" << mSname << endl; //(3)顯示的層級向下走一級 level++; //(4)輸出所包含的子內容(可能是文件,也可能是子目錄) //遍歷目錄中的文件和子目錄 for (auto iter = mChild.begin(); iter != mChild.end(); ++iter) { (*iter)->ShowName(level); }//end for } /*virtual*/ int Add(JadeFileSystem* pfilesys) { mChild.push_back(pfilesys); return 0; } /*virtual*/ int Remove(JadeFileSystem* pfilesys) { mChild.remove(pfilesys); return 0; } public: virtual JadeDir* ifCompositeObj() { return this; } public: virtual int countNumOfFiles() { int iNumOfFiles = 0; for (auto iter = mChild.begin(); iter != mChild.end(); ++iter) { iNumOfFiles += (*iter)->countNumOfFiles();//遞歸調用 } return iNumOfFiles; } private: /// <summary> /// 文件名 /// </summary> string mSname; /// <summary> /// /// </summary> list<JadeFileSystem*> mChild; }; } #endif /*****************************************************************//** * \file JadeFileSystem.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef JADEFILESYSTEM_H #define JADEFILESYSTEM_H #include <iostream> #include <sstream> #include <vector> #include <list> using namespace std; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuJadeCompositePattern { class JadeDir; /// <summary> /// /// </summary> class JadeFileSystem { public: /// <summary> /// 顯示名字,參數level用於表示顯示的層級,用於顯示對齊 /// </summary> /// <param name="level"></param> virtual void ShowName(int level) = 0; /// <summary> /// 做父類時析構函數應該爲虛函數 /// </summary> virtual ~JadeFileSystem() {} public: /// <summary> /// /// </summary> /// <returns></returns> virtual JadeDir* ifCompositeObj() { return nullptr; } public: /// <summary> /// /// </summary> /// <returns></returns> virtual int countNumOfFiles() = 0; //統計目錄下包含的文件個數 }; } #endif
/*****************************************************************//** * \file GeovinDu.h * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #pragma once #ifndef GEOVINDU_H #define GEOVINDU_H #include <iostream> #include <sstream> #include <vector> #include <list> #include "GoldFile.h" #include "GoldDir.h" #include "PearFileSystem.h" #include "PearDir.h" #include "PearFile.h" #include "JadeDir.h" #include "JadeFile.h" #include "JadeFileSystem.h" using namespace std; using namespace DuPearCompositePattern; using namespace DuJadeCompositePattern; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuCompositePattern { /// <summary> /// /// </summary> class GeovinDu { private: public: /// <summary> ///示例 /// </summary> void displaySimple(); /// <summary> /// /// </summary> void displayPearSimple(); /// <summary> /// /// </summary> void displayJadeSimple(); }; } #endif /*****************************************************************//** * \file GeovinDu.cpp * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ #include "GeovinDu.h" using namespace std; using namespace DuPearCompositePattern; using namespace DuJadeCompositePattern; /** * @brief 類庫空間名 * geovindu edit * */ namespace DuCompositePattern { /// <summary> /// 示例 /// </summary> void GeovinDu::displaySimple() { //(1)創建各種目錄,文件對象 DuCompositePattern::GoldDir* pdir1 = new DuCompositePattern::GoldDir("root"); //------- DuCompositePattern::GoldFile* pfile1 = new DuCompositePattern::GoldFile("common.mk"); DuCompositePattern::GoldFile* pfile2 = new DuCompositePattern::GoldFile("config.mk"); DuCompositePattern::GoldFile* pfile3 = new DuCompositePattern::GoldFile("makefile"); //------- DuCompositePattern::GoldDir* pdir2 = new DuCompositePattern::GoldDir("app"); DuCompositePattern::GoldFile* pfile4 = new DuCompositePattern::GoldFile("nginx.c"); DuCompositePattern::GoldFile* pfile5 = new DuCompositePattern::GoldFile("ngx_conf.c"); //------- DuCompositePattern::GoldDir* pdir3 = new DuCompositePattern::GoldDir("signal"); DuCompositePattern::GoldFile* pfile6 = new DuCompositePattern::GoldFile("ngx_signal.c"); //------- DuCompositePattern::GoldDir* pdir4 = new DuCompositePattern::GoldDir("_include"); DuCompositePattern::GoldFile* pfile7 = new DuCompositePattern::GoldFile("ngx_func.h"); DuCompositePattern::GoldFile* pfile8 = new DuCompositePattern::GoldFile("ngx_signal.h"); //(2)構造樹形目錄結構 pdir1->AddFile(pfile1); pdir1->AddFile(pfile2); pdir1->AddFile(pfile3); //------- pdir1->AddDir(pdir2); pdir2->AddFile(pfile4); pdir2->AddFile(pfile5); //------- pdir1->AddDir(pdir3); pdir3->AddFile(pfile6); //------- pdir1->AddDir(pdir4); pdir4->AddFile(pfile7); pdir4->AddFile(pfile8); //(3)輸出整個目錄結構,只要調用根目錄的ShowName方法即可,每個子目錄都有自己的ShowName方法負責自己旗下的文件和目錄的顯示 pdir1->ShowName("");//縮進字符剛開始可以爲空 //(4)釋放資源 delete pfile8; delete pfile7; delete pdir4; //------- delete pfile6; delete pdir3; //------- delete pfile5; delete pfile4; delete pdir2; //------- delete pfile3; delete pfile2; delete pfile1; delete pdir1; } /// <summary> /// /// </summary> void GeovinDu::displayPearSimple() { //(1)創建各種目錄,文件對象 DuPearCompositePattern::PearFileSystem* pdir1 = new DuPearCompositePattern::PearDir("root"); //------- DuPearCompositePattern::PearFileSystem* pfile1 = new DuPearCompositePattern::PearFile("common.mk"); DuPearCompositePattern::PearFileSystem* pfile2 = new DuPearCompositePattern::PearFile("config.mk"); DuPearCompositePattern::PearFileSystem* pfile3 = new DuPearCompositePattern::PearFile("makefile"); //------- DuPearCompositePattern::PearFileSystem* pdir2 = new DuPearCompositePattern::PearDir("app"); DuPearCompositePattern::PearFileSystem* pfile4 = new DuPearCompositePattern::PearFile("nginx.c"); DuPearCompositePattern::PearFileSystem* pfile5 = new DuPearCompositePattern::PearFile("ngx_conf.c"); //------- DuPearCompositePattern::PearFileSystem* pdir3 = new DuPearCompositePattern::PearDir("signal"); DuPearCompositePattern::PearFileSystem* pfile6 = new DuPearCompositePattern::PearFile("ngx_signal.c"); //------- DuPearCompositePattern::PearFileSystem* pdir4 = new DuPearCompositePattern::PearDir("_include"); DuPearCompositePattern::PearFileSystem* pfile7 = new DuPearCompositePattern::PearFile("ngx_func.h"); DuPearCompositePattern::PearFileSystem* pfile8 = new DuPearCompositePattern::PearFile("ngx_signal.h"); //(2)構造樹形目錄結構 pdir1->Add(pfile1); pdir1->Add(pfile2); pdir1->Add(pfile3); //------- pdir1->Add(pdir2); pdir2->Add(pfile4); pdir2->Add(pfile5); //------- pdir1->Add(pdir3); pdir3->Add(pfile6); //------- pdir1->Add(pdir4); pdir4->Add(pfile7); pdir4->Add(pfile8); //(3)輸出整個目錄結構,只要調用根目錄的ShowName方法即可,每個子目錄都有自己的ShowName方法負責自己旗下的文件和目錄的顯示 pdir1->ShowName(0); //(4)釋放資源 delete pfile8; delete pfile7; delete pdir4; //------- delete pfile6; delete pdir3; //------- delete pfile5; delete pfile4; delete pdir2; //------- delete pfile3; delete pfile2; delete pfile1; delete pdir1; } /// <summary> /// /// </summary> void GeovinDu::displayJadeSimple() { //(1)創建各種目錄,文件對象 DuJadeCompositePattern::JadeDir* pdir1 = new DuJadeCompositePattern::JadeDir("root"); //------- DuJadeCompositePattern::JadeFileSystem* pfile1 = new DuJadeCompositePattern::JadeFile("common.mk"); DuJadeCompositePattern::JadeFileSystem* pfile2 = new DuJadeCompositePattern::JadeFile("config.mk"); DuJadeCompositePattern::JadeFileSystem* pfile3 = new DuJadeCompositePattern::JadeFile("makefile"); //------- DuJadeCompositePattern::JadeDir* pdir2 = new DuJadeCompositePattern::JadeDir("app"); if (pdir2->ifCompositeObj() != nullptr) { //是個組合對象,可以向其中增加單個對象和其它組合對象 } if (dynamic_cast<DuJadeCompositePattern::JadeDir*>(pdir2) != nullptr) { //是個組合對象,可以向其中增加單個對象和其它組合對象 } DuJadeCompositePattern::JadeFileSystem* pfile4 = new DuJadeCompositePattern::JadeFile("nginx.c"); DuJadeCompositePattern::JadeFileSystem* pfile5 = new DuJadeCompositePattern::JadeFile("ngx_conf.c"); //------- DuJadeCompositePattern::JadeDir* pdir3 = new DuJadeCompositePattern::JadeDir("signal"); DuJadeCompositePattern::JadeFileSystem* pfile6 = new DuJadeCompositePattern::JadeFile("ngx_signal.c"); //------- DuJadeCompositePattern::JadeDir* pdir4 = new DuJadeCompositePattern::JadeDir("_include"); DuJadeCompositePattern::JadeFileSystem* pfile7 = new DuJadeCompositePattern::JadeFile("ngx_func.h"); DuJadeCompositePattern::JadeFileSystem* pfile8 = new DuJadeCompositePattern::JadeFile("ngx_signal.h"); //(2)構造樹形目錄結構 //這部分內容基本沒變, pdir1->Add(pfile1); pdir1->Add(pfile2); pdir1->Add(pfile3); //------- pdir1->Add(pdir2); pdir2->Add(pfile4); pdir2->Add(pfile5); //------- pdir1->Add(pdir3); pdir3->Add(pfile6); //------- pdir1->Add(pdir4); pdir4->Add(pfile7); pdir4->Add(pfile8); //(3)輸出整個目錄結構,只要調用根目錄的ShowName方法即可,每個子目錄都有自己的ShowName方法負責自己旗下的文件和目錄的顯示 pdir1->ShowName(0); cout << "文件的數量爲:" << pdir1->countNumOfFiles() << endl; //(4)釋放資源 //這部分內容基本沒變, delete pfile8; delete pfile7; delete pdir4; //------- delete pfile6; delete pdir3; //------- delete pfile5; delete pfile4; delete pdir2; //------- delete pfile3; delete pfile2; delete pfile1; delete pdir1; } }
調用:
/*****************************************************************//** * \file ConsoleDuCompositePattern.cpp * \brief 組合模式CompositePattern 亦稱: 對象樹、Object Tree、Composite c++14 * 2023年5月28日 塗聚文 Geovin Du Visual Studio 2022 edit. * \author geovindu * \date May 2023 *********************************************************************/ // ConsoleDuCompositePattern.cpp : 此文件包含 "main" 函數。程序執行將在此處開始並結束。 //2023年5月22日 塗聚文 Geovin Du Visual Studio 2022 edit. #define _UNICODE #include <iostream> #include <vector> #include <list> #include "GeovinDu.h" #ifdef _DEBUG //只在Debug(調試)模式下 #ifndef DEBUG_NEW #define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定義new運算符 #define new DEBUG_NEW #endif #endif using namespace std; using namespace DuCompositePattern; int main() { _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出時檢測內存泄漏並顯示到“輸出”窗口 std::cout << "Hello World!塗聚文 Geovin Du\n"; GeovinDu geovin; geovin.displaySimple(); cout << "*********" << endl; geovin.displayPearSimple(); cout << "*********" << endl; geovin.displayJadeSimple(); system("pause"); return 0; } // 運行程序: Ctrl + F5 或調試 >“開始執行(不調試)”菜單 // 調試程序: F5 或調試 >“開始調試”菜單 // 入門使用技巧: // 1. 使用解決方案資源管理器窗口添加/管理文件 // 2. 使用團隊資源管理器窗口連接到源代碼管理 // 3. 使用輸出窗口查看生成輸出和其他消息 // 4. 使用錯誤列表窗口查看錯誤 // 5. 轉到“項目”>“添加新項”以創建新的代碼文件,或轉到“項目”>“添加現有項”以將現有代碼文件添加到項目 // 6. 將來,若要再次打開此項目,請轉到“文件”>“打開”>“項目”並選擇 .sln 文件 #define UNICODE
輸出:
Hello World!塗聚文 Geovin Du +root -common.mk -config.mk -makefile +app -nginx.c -ngx_conf.c +signal -ngx_signal.c +_include -ngx_func.h -ngx_signal.h ********* +root -common.mk -config.mk -makefile +app -nginx.c -ngx_conf.c +signal -ngx_signal.c +_include -ngx_func.h -ngx_signal.h ********* +root -common.mk -config.mk -makefile +app -nginx.c -ngx_conf.c +signal -ngx_signal.c +_include -ngx_func.h -ngx_signal.h 文件的數量爲:8 請按任意鍵繼續. . .