您好,登錄后才能下訂單哦!
設計模式3 創建型模型
目錄: 簡單工廠模式 工廠方法模式 抽象工廠模式 單例模式
簡單工廠 模型
chunli@linux:~$ cat main.cpp //設計模式:簡單工廠 模型 #include<iostream> using namespace std; class Fruit { public: Fruit(string kind) { this->kind = kind; if(kind == "apple") {} else if (kind == "banana") {} } void getName() { if(kind == "apple") { cout << "我是蘋果" << endl; } else if(kind == "banana") { cout << "我是香蕉" << endl; } } private: string kind;//代表水果種類 }; int main() { Fruit* apple = new Fruit("apple"); apple->getName(); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是蘋果 chunli@linux:~$
出現的問題:如果再添加新的水果,越來越復雜
chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是蘋果 我是香蕉 chunli@linux:~$ chunli@linux:~$ chunli@linux:~$ cat main.cpp //設計模式:簡單工廠 實現 #include<iostream> using namespace std; //抽象的水果類 class Fruit { public: virtual void getName() = 0; }; //實際水果 class Apple:public Fruit { public: virtual void getName() { cout << "我是蘋果"<<endl; } }; class Banana:public Fruit { public: virtual void getName() { cout << "我是香蕉"<<endl; } }; class Factory { public: //水果生產器 Fruit* createFruit(string kind) { if(kind == "apple") { return new Apple; } else if(kind == "banana") { return new Banana; } return NULL; } }; int main() { Factory *factory = new Factory; Fruit *apple = factory->createFruit("apple"); apple->getName(); Fruit *banana = factory->createFruit("banana"); banana->getName(); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是蘋果 我是香蕉 chunli@linux:~$
簡單工廠優缺點,GOF不承認.但是依然有很多人在用.
優點:
1,實現了對象的創建和是使用的分離.
2,不知要記住具體的類名,記住參數即可,減少使用者的記憶量.
缺點:
1,對工廠類的職責過重,一旦不能工作,紫銅受到影響.
2,增加系統中類的個數,負責度和理解度增加.
3,違反了開閉原則,添加新的產品需要修改工廠邏輯,工廠越來越復雜. +
適用場景:
1,工廠類負責創建的對象比較少,由于創建的對象比較少,不會造成工廠方法中的而業務邏輯太過復雜.
2,客戶端只知道傳入工廠類的參數,對于如何創建對象并不關心.
=========================================
工廠方法模式,
看圖[工廠方法模式的案例]
chunli@linux:~$ cat main.cpp //工廠模式 //符合開閉原則,添加一個產品不用修改其他的代碼 //簡單工廠模式 + "開閉原則" = 工廠方法模式 #include<iostream> using namespace std; /////////////// 抽象類 ////////////////////////// class Fruit //抽象的水果類 { public: virtual void getName() = 0; virtual ~Fruit(){} }; class AbstractFactory//抽象工廠 { public: virtual Fruit* createFruit() = 0; virtual ~AbstractFactory(){} }; ////////////// 實現類 ////////////////// //1,蘋果 class Apple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是蘋果" <<endl; } }; class AppleFactory:public AbstractFactory//蘋果的工廠 { public: virtual Fruit* createFruit() { return new Apple; } }; //2,香蕉 class Banana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是香蕉" <<endl; } }; class BananaFactory:public AbstractFactory//香蕉的工廠 { public: virtual Fruit* createFruit() { return new Banana; } }; //3 添加一個產品,梨 class Pear:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是梨" <<endl; } }; class PearFactory:public AbstractFactory//香蕉的工廠 { public: virtual Fruit* createFruit() { return new Pear; } }; int main() { AbstractFactory* bananaFactory = new BananaFactory;//來一個香蕉的工廠 Fruit* banana = bananaFactory->createFruit(); //生產一個香蕉 banana->getName(); delete bananaFactory; delete banana; AbstractFactory* applefactory = new AppleFactory; Fruit* apple = applefactory->createFruit(); apple->getName(); delete applefactory; delete apple; AbstractFactory* pearfactory = new PearFactory; Fruit* pear = pearfactory->createFruit(); pear->getName(); delete pearfactory; delete pear; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是香蕉 我是蘋果 我是梨 chunli@linux:~$
工廠方法模式的優缺點
優點:
1. 不需要記住具體類名,甚至連具體參數 都不用記憶。
2. 實現了對象創建和使用的分離。
3. 系統的可擴展性也就變得非常好,無需修改接口和原類。
缺點:
1. 增加系統中類的個數,復雜度和理解度增加。
2. 增加了系統的抽象性和理解難度。
適用場景
1. 客戶端不知道它所需要的對象的類。
2. 抽象工廠類通過其子類來指定創建哪個對象。
==========================================
抽象工廠模式:
看圖:[抽象工廠模式]
chunli@linux:~$ cat main.cpp //抽象工廠方法 模式 #include<iostream> using namespace std; /////////////// 抽象 水果 類 ////////////////////////// class Fruit //抽象的水果類 { public: virtual void getName() = 0; virtual ~Fruit(){} }; ////////////// 實現 水果類 ////////////////// class USAApple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是 美國 蘋果" <<endl; } }; class USABanana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是 美國 香蕉" <<endl; } }; class ChinaApple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是 中國 蘋果" <<endl; } }; class ChinaBanana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是 中國 香蕉" <<endl; } }; ////////// 定義一個抽象工廠,是面向產品族 進行生產 /////// class AbstractFactory//抽象工廠 { public: virtual Fruit* createApple() = 0; virtual Fruit* createBanana() = 0; virtual ~AbstractFactory(){} }; /////////美國的具體工廠//////////////////////////////////////// class USAFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new USAApple; } virtual Fruit* createBanana() { return new USABanana; } }; ////中國的具體工廠/////////////////////////////////////// class ChinaFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new ChinaApple; } virtual Fruit* createBanana() { return new ChinaBanana; } }; int main() { //想要一個美國的香蕉 //1,來一個美國的工廠 AbstractFactory* usaf = new USAFactory; Fruit* usabanana = usaf->createBanana(); usabanana->getName(); delete usaf; delete usabanana; //想要一個中國的蘋果 //1,來一個中國的工廠 AbstractFactory* chinaf = new ChinaFactory; Fruit* chinaapple = chinaf->createApple(); chinaapple->getName(); delete chinaf; delete chinaapple; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是 美國 香蕉 我是 中國 蘋果 chunli@linux:~$
添加一個日本的工廠,符合 開閉原則
chunli@linux:~$ cat main.cpp //抽象工廠方法 模式 #include<iostream> using namespace std; /////////////// 抽象 水果 類 ////////////////////////// class Fruit //抽象的水果類 { public: virtual void getName() = 0; virtual ~Fruit(){} }; ////////////// 實現 水果類 ////////////////// class USAApple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是 美國 蘋果" <<endl; } }; class USABanana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是 美國 香蕉" <<endl; } }; class ChinaApple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是 中國 蘋果" <<endl; } }; class ChinaBanana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是 中國 香蕉" <<endl; } }; class JapanApple:public Fruit//蘋果類 { public: virtual void getName() { cout << "我是 Japan 蘋果" <<endl; } }; class JapanBanana:public Fruit//香蕉類 { public: virtual void getName() { cout << "我是 Japan 香蕉" <<endl; } }; ////////// 定義一個抽象工廠,是面向產品族 進行生產 /////// class AbstractFactory//抽象工廠 { public: virtual Fruit* createApple() = 0; virtual Fruit* createBanana() = 0; virtual ~AbstractFactory(){} }; /////////美國的具體工廠//////////////////////////////////////// class USAFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new USAApple; } virtual Fruit* createBanana() { return new USABanana; } }; ////中國的具體工廠/////////////////////////////////////// class ChinaFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new ChinaApple; } virtual Fruit* createBanana() { return new ChinaBanana; } }; ////日本的具體工廠/////////////////////////////////////// class JapanFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new JapanApple; } virtual Fruit* createBanana() { return new JapanBanana; } }; int main() { //想要一個美國的香蕉 //1,來一個美國的工廠 AbstractFactory* usaf = new USAFactory; Fruit* usabanana = usaf->createBanana(); usabanana->getName(); delete usaf; delete usabanana; //想要一個中國的蘋果 //1,來一個中國的工廠 AbstractFactory* chinaf = new ChinaFactory; Fruit* chinaapple = chinaf->createApple(); chinaapple->getName(); delete chinaf; delete chinaapple; //想要一個Japan的蘋果 //1,來一個Japan的工廠 AbstractFactory* japanf = new JapanFactory; Fruit* japanapple = japanf->createApple(); japanapple->getName(); delete japanf; delete japanapple; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是 美國 香蕉 我是 中國 蘋果 我是 Japan 蘋果 chunli@linux:~$
添加一種新的水果,梨.開閉原則被打破
chunli@linux:~$ cat main.cpp //抽象工廠方法 模式 #include<iostream> using namespace std; /////////////// 抽象 水果 類 ////////////////////////// class Fruit //抽象的水果類 { public: virtual void getName() = 0; virtual ~Fruit(){} }; ////////////// 實現 水果類 ,美國&中國&日本 -> 蘋果,香蕉,梨////////////////// class USAApple:public Fruit { public: virtual void getName() { cout << "我是 美國 蘋果" <<endl; } }; class USABanana:public Fruit { public: virtual void getName() { cout << "我是 美國 香蕉" <<endl; } }; class USAPear:public Fruit { public: virtual void getName() { cout << "我是 美國 pear" <<endl; } }; class ChinaApple:public Fruit { public: virtual void getName() { cout << "我是 中國 蘋果" <<endl; } }; class ChinaBanana:public Fruit { public: virtual void getName() { cout << "我是 中國 香蕉" <<endl; } }; class ChinaPear:public Fruit { public: virtual void getName() { cout << "我是 中國 pear" <<endl; } }; class JapanApple:public Fruit { public: virtual void getName() { cout << "我是 Japan 蘋果" <<endl; } }; class JapanBanana:public Fruit { public: virtual void getName() { cout << "我是 Japan 香蕉" <<endl; } }; class JapanPear:public Fruit { public: virtual void getName() { cout << "我是 Japan pear" <<endl; } }; ////////// 定義一個抽象工廠,是面向產品族 進行生產 /////// class AbstractFactory//抽象工廠 { public: virtual Fruit* createApple() = 0; virtual Fruit* createBanana() = 0; virtual Fruit* createPear() = 0; virtual ~AbstractFactory(){} }; /////////美國的具體工廠//////////////////////////////////////// class USAFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new USAApple; } virtual Fruit* createBanana() { return new USABanana; } virtual Fruit* createPear() { return new USAPear; } }; ////中國的具體工廠/////////////////////////////////////// class ChinaFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new ChinaApple; } virtual Fruit* createBanana() { return new ChinaBanana; } virtual Fruit* createPear() { return new ChinaPear; } }; ////日本的具體工廠/////////////////////////////////////// class JapanFactory:public AbstractFactory { public: virtual Fruit* createApple() { return new JapanApple; } virtual Fruit* createBanana() { return new JapanBanana; } virtual Fruit* createPear() { return new JapanPear; } }; int main() { //想要一個美國的香蕉 //1,來一個美國的工廠 AbstractFactory* usaf = new USAFactory; Fruit* usabanana = usaf->createBanana(); usabanana->getName(); delete usaf; delete usabanana; //想要一個中國的蘋果 //1,來一個中國的工廠 AbstractFactory* chinaf = new ChinaFactory; Fruit* chinaapple = chinaf->createApple(); chinaapple->getName(); delete chinaf; delete chinaapple; //想要一個Japan的pear //1,來一個Japan的工廠 AbstractFactory* japanf = new JapanFactory; Fruit* japanpear = japanf->createPear(); japanpear->getName(); delete japanf; delete japanpear; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 我是 美國 香蕉 我是 中國 蘋果 我是 Japan pear chunli@linux:~$
抽象工廠模式的優缺點
優點:
1. 擁有工廠方法模式的優點
2. 當一個產品族中的多個對象被設計成一起工作時,它能夠保證客戶端
始終只使用同一個產品族中的對象。
3 增加新的產品族很方便,無須修改已有系統,符合“開閉原則”。
缺點:
1. 增加新的產品等級結構麻煩,需要對原有系統進行較大的修改,甚至需
要修改抽象層代碼,這顯然會帶來較大的不便,違背了“開閉原則”。
適用場景
(1) 系統中有多于一個的產品族。而每次只使用其中某一產品族。可以通過
配置文件等方式來使得用戶可以動態改變產品族,也可以很方便地增加新的產
品族。
(2) 產品等級結構穩定。設計完成之后,不會向系統中增加新的產品等級結
構或者刪除已有的產品等級結構。
作業:
設計一個電腦主板架構,電腦包括(顯卡,內存,CPU)3個固定的插口,
顯卡具有顯示功能(display,功能實現只要打印出意義即可), 內存具有存
儲功能(storage),cpu具有計算功能(calculate)。
現有Intel廠商,nvidia廠商,Kingston 廠商,均會生產以上三種硬件。
要求組裝兩臺電腦,
1臺(Intel的CPU,Intel的顯卡,Intel的內存)
1臺(Intel的CPU, nvidia的顯卡,Kingston 的內存)
用抽象工廠模式實現。
抽象工廠方法,intel系列產品,組裝一臺Intel的電腦
chunli@linux:~$ cat main.cpp #include<iostream> using namespace std; /* 抽象層 */ class CPU { public: virtual void caculate() = 0; }; class Card { public: virtual void dispaly() = 0; }; class Memory { public: virtual void storage() = 0; }; /* 抽象工廠 */ class AbstractFactory { public: virtual CPU* createCPU() = 0; virtual Card* createCard() = 0; virtual Memory* createMem() = 0; }; /* 抽象架構 */ class Computer { public: Computer(CPU* cpu,Card* card,Memory* mem) { this->cpu = cpu; this->card = card; this->mem = mem; } void work() { this->cpu->caculate(); this->card->dispaly(); this->mem->storage(); } private: CPU* cpu; Card* card; Memory* mem; }; /*------抽象完成--------*/ /* 實現層 */ class IntelCPU:public CPU { public: virtual void caculate() { cout << "開始計算" << endl; }; }; class IntelCard:public Card { public: virtual void dispaly() { cout << "開始顯示 " << endl; }; }; class IntelMem:public Memory { public: virtual void storage() { cout << "開始存儲" << endl; }; }; class IntelFactory:public AbstractFactory { public: virtual CPU* createCPU() { return new IntelCPU; } virtual Card* createCard() { return new IntelCard; } virtual Memory* createMem() { return new IntelMem; } }; int main() { //組裝一臺電腦 //創建一個Intel的工廠 AbstractFactory *intelFactory = new IntelFactory;//父類指針 指向 子類對象 CPU* intelCPU = intelFactory->createCPU(); Card* intelCard = intelFactory->createCard(); Memory* intelMem = intelFactory->createMem(); Computer* com1 = new Computer(intelCPU,intelCard,intelMem); com1->work(); cout << "-------------------------" << endl; return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 開始計算 開始顯示 開始存儲 ------------------------- chunli@linux:~$
抽象工廠方法,intel系列產品,組裝一臺 臺式機
chunli@linux:~$ cat main.cpp #include<iostream> using namespace std; /* 抽象層 */ class CPU { public: virtual void caculate() = 0; }; class Card { public: virtual void dispaly() = 0; }; class Memory { public: virtual void storage() = 0; }; /* 抽象工廠 */ class AbstractFactory { public: virtual CPU* createCPU() = 0; virtual Card* createCard() = 0; virtual Memory* createMem() = 0; }; /* 抽象架構 */ class Computer { public: Computer(CPU* cpu,Card* card,Memory* mem) { this->cpu = cpu; this->card = card; this->mem = mem; } void work() { this->cpu->caculate(); this->card->dispaly(); this->mem->storage(); } private: CPU* cpu; Card* card; Memory* mem; }; /*------抽象完成--------*/ /* 實現層 Intel廠商 */ class IntelCPU:public CPU { public: virtual void caculate() { cout << "Intel cpu 開始計算" << endl; }; }; class IntelCard:public Card { public: virtual void dispaly() { cout << "intel card 開始顯示 " << endl; }; }; class IntelMem:public Memory { public: virtual void storage() { cout << "intel mem 開始存儲" << endl; }; }; class IntelFactory:public AbstractFactory { public: virtual CPU* createCPU() { return new IntelCPU; } virtual Card* createCard() { return new IntelCard; } virtual Memory* createMem() { return new IntelMem; } }; /* 實現層 英偉達 廠商 */ class NvidiaCPU:public CPU { public: virtual void caculate() { cout << "Nvidia cpu 開始計算" << endl; }; }; class NvidiaCard:public Card { public: virtual void dispaly() { cout << "Nvidia card 開始顯示 " << endl; }; }; class NvidiaMem:public Memory { public: virtual void storage() { cout << "Nvidia mem 開始存儲" << endl; }; }; class NvidiaFactory:public AbstractFactory { public: virtual CPU* createCPU() { return new NvidiaCPU; } virtual Card* createCard() { return new NvidiaCard; } virtual Memory* createMem() { return new NvidiaMem; } }; /* 實現層 金士頓 廠商 */ class KingstonCPU:public CPU { public: virtual void caculate() { cout << "Kingston cpu 開始計算" << endl; }; }; class KingstonCard:public Card { public: virtual void dispaly() { cout << "Kingston card 開始顯示 " << endl; }; }; class KingstonMem:public Memory { public: virtual void storage() { cout << "Kingston mem 開始存儲" << endl; }; }; class KingstonFactory:public AbstractFactory { public: virtual CPU* createCPU() { return new KingstonCPU; } virtual Card* createCard() { return new KingstonCard; } virtual Memory* createMem() { return new KingstonMem; } }; int main() { //組裝一臺兼容機,要Intel的cpu,nvidia的card,kingston的mem AbstractFactory *intelFactory = new IntelFactory; AbstractFactory *nvidiaFactory = new NvidiaFactory; AbstractFactory *kingstonFactory = new KingstonFactory; CPU* intelCPU = intelFactory->createCPU(); Card* nvidiaCard = nvidiaFactory->createCard(); Memory* kingstonlMem = kingstonFactory->createMem(); Computer* computer = new Computer(intelCPU,nvidiaCard,kingstonlMem); computer->work(); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out Intel cpu 開始計算 Nvidia card 開始顯示 Kingston mem 開始存儲 chunli@linux:~$
============================================
單例模式,整個程序中只有一個對象.
1,餓漢式
chunli@linux:~$ cat main.cpp #include<iostream> using namespace std; // 三個要點: // 一是某個類只能有一個實例; // 二是它必須自行創建這個實例; // 三是它必須自行向整個系統提供這個實例。 class Singleton { public: static Singleton* getInstance() { return instance; } private: Singleton(){} static Singleton* instance; }; //在編譯期間,就已經確定這個唯一的實例了 Singleton* Singleton::instance = new Singleton;//餓漢式 int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); if(s1 == s2) { cout << "s1 == s2 " << endl; } else { cout << "s1 != s2 " << endl; } return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out s1 == s2 chunli@linux:~$
2,懶漢式
chunli@linux:~$ cat main.cpp #include<iostream> using namespace std; // 三個要點: // 一是某個類只能有一個實例; // 二是它必須自行創建這個實例; // 三是它必須自行向整個系統提供這個實例。 class Singleton { public: static Singleton* getInstance() { if(instance == NULL) //懶漢式 多線程危險 { instance = new Singleton; } return instance; } private: Singleton(){} static Singleton* instance; }; Singleton* Singleton::instance = NULL;//懶漢式 int main() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); if(s1 == s2) { cout << "s1 == s2 " << endl; } else { cout << "s1 != s2 " << endl; } return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out s1 == s2 chunli@linux:~$
單例模式,懶漢式多線程問題
class Singleton { public: static Singleton* getInstance() { //加鎖 if(instance == NULL) //懶漢式 多線程危險 { instance = new Singleton; } //解鎖 return instance; } private: Singleton(){} static Singleton* instance; }; Singleton* Singleton::instance = NULL;//懶漢式
單例模式,打印機案例,單例的回收
chunli@linux:~$ cat main.cpp #include<iostream> using namespace std; // 三個要點: // 一是某個類只能有一個實例; // 二是它必須自行創建這個實例; // 三是它必須自行向整個系統提供這個實例。 class Printer { public: static Printer* getInstance() { if(instance == NULL) //懶漢式 多線程危險 { instance = new Printer; } return instance; } void printf(string text) { sequence++; cout << sequence << " 打印的內容是" << text << endl; } static int getCount()//返回已經打印了多少次 { return sequence; } private: class Garbo //單例的垃圾回收機制 { public: ~Garbo() { if(instance != NULL) { cout << "開始析構 instance" << endl; delete instance; } } }; private: Printer(){} static int sequence; //記錄打印機已經打印了多少條數據 static Printer* instance; static Garbo garbo;//在靜態區開辟空間,程序運行結束時,釋放instance }; Printer* Printer::instance = NULL;//懶漢式 int Printer::sequence = 0; Printer::Garbo Printer::garbo; int main() { Printer *p1 = Printer::getInstance(); p1->printf(" 我的簡歷.doc"); Printer *p2 = Printer::getInstance(); p2->printf(" LOL皮膚.jpg"); Printer *p3 = Printer::getInstance(); p3->printf(" 離職簡歷.doc"); return 0; } chunli@linux:~$ g++ main.cpp -Wall && ./a.out 1 打印的內容是 我的簡歷.doc 2 打印的內容是 LOL皮膚.jpg 3 打印的內容是 離職簡歷.doc 開始析構 instance chunli@linux:~$
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。