*1、工廠模式:簡單工廠模式、工廠方法模式、抽象工廠模式
1)、簡單工廠模式:主要特點(diǎn)是需要在工廠類中做判斷,從而創(chuàng)造相應(yīng)的產(chǎn)品,當(dāng)增加新產(chǎn)品時(shí),需要修改工廠類。
#include "iostream"
using namespace std;typedef enum
{T80 = 1,T99
}TankType;class Tank
{
public:virtual void message() = 0;
};class Tank80 :public Tank
{
public:void message(){cout << "Tank80" << endl;}
};class Tank99 :public Tank
{
public:void message(){printf("T99");cout << "Tank99" << endl;}
};class TankFactory
{
public:Tank* createTank(TankType type){switch (type){case 1:return new Tank80();break;case 2:return new Tank99();break;default:return NULL;break;}}
};int _tmain(int argc, _TCHAR* argv[])
{TankFactory *factory = new TankFactory();TankType type = T99;factory->createTank(type)->message();return 0;
}
2)、工廠方法模式:是指定義一個(gè)創(chuàng)建對(duì)象的接口,讓子類決定實(shí)例化哪一個(gè)類,Factory Method使一個(gè)類的實(shí)例化延遲到其子類。
? ? ? ? 主要解決:主要解決接口選擇的問題。,多個(gè)工廠,多個(gè)產(chǎn)品,每個(gè)產(chǎn)品對(duì)應(yīng)于一個(gè)工廠。
? ? ? ? 何時(shí)使用:我們明確地計(jì)劃不同條件下創(chuàng)建不同實(shí)例時(shí)。
? ? ? ? 如何解決:讓其子類實(shí)現(xiàn)工廠接口,返回的也是一個(gè)抽象的產(chǎn)品。
? ? ? ? 關(guān)鍵代碼:創(chuàng)建過程在其子類執(zhí)行。
? ? ? ? 缺點(diǎn):每增加一種產(chǎn)品,就需要增加一個(gè)對(duì)象工廠。相比簡單工廠模式,工廠方法模式需要定義更多的類。
#include "iostream"
using namespace std;class Product
{
public:virtual void show() = 0;
};class Product_A : public Product
{
public:void show(){cout << "Product_A" << endl;}
};class Product_B : public Product
{
public:void show(){cout << "Product_B" << endl;}
};class Factory
{
public:virtual Product* create() = 0;
};class Factory_A : public Factory
{
public:Product* create(){return new Product_A;}
};class Factory_B : public Factory
{
public:Product* create(){return new Product_B;}
};int _tmain(int argc, _TCHAR* argv[])
{Factory_A* productA = new Factory_A();Factory_B* productB = new Factory_B();productA->create()->show();productB->create()->show();system("pause");return 0;
}
3)、抽象工廠模式:提供一個(gè)創(chuàng)建一系列相關(guān)或相互依賴的對(duì)象接口,而無需指定它們的具體類。
?? ?主要解決:主要解決接口選擇的問題,多個(gè)工廠,多個(gè)產(chǎn)品,并且每個(gè)產(chǎn)品可以包含多個(gè)型號(hào)。此時(shí)工廠和產(chǎn)品都是通過? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?虛基類的方式構(gòu)建。每一個(gè)工廠類可以生產(chǎn)同一個(gè)產(chǎn)品的多個(gè)型號(hào)。
?? ?何時(shí)使用:系統(tǒng)的產(chǎn)品有多于一個(gè)的產(chǎn)品族,而系統(tǒng)只消費(fèi)其中某一族的產(chǎn)品。
?? ?如何解決:在一個(gè)產(chǎn)品族里面,定義多個(gè)產(chǎn)品。
?? ? 關(guān)鍵代碼:在一個(gè)工廠里聚合多個(gè)同類產(chǎn)品。
?? ? 缺點(diǎn):產(chǎn)品族擴(kuò)展非常困難,要增加一個(gè)系列的某一產(chǎn)品,既要在抽象的 Creator 里加代碼,又要在具體的里面加代碼。
#include "iostream"
using namespace std;//定義抽象類
class product1
{
public:virtual void show() = 0;
};//定義具體類
class product_A1 :public product1
{
public:void show(){ cout << "product A1" << endl; }
};class product_B1 :public product1
{
public:void show(){ cout << "product B1" << endl; }
};//定義抽象類
class product2
{
public:virtual void show() = 0;
};//定義具體類
class product_A2 :public product2
{
public:void show(){ cout << "product A2" << endl; }
};class product_B2 :public product2
{
public:void show(){ cout << "product B2" << endl; }
};class Factory
{
public:virtual product1 *creat1() = 0;virtual product2 *creat2() = 0;
};class FactoryA:public Factory
{
public:product1 *creat1(){ return new product_A1(); }product2 *creat2(){ return new product_A2(); }
};class FactoryB:public Factory
{
public:product1 *creat1(){ return new product_B1(); }product2 *creat2(){ return new product_B2(); }
};int _tmain(int argc, _TCHAR* argv[])
{FactoryA *factoryA = new FactoryA();factoryA->creat1()->show();factoryA->creat2()->show();FactoryB *factoryB = new FactoryB();factoryB->creat1()->show();factoryB->creat2()->show();return 0;
}
*2、 策略模式:是指定義一系列的算法,把它們一個(gè)個(gè)封裝起來,并且使它們可以互相替換。使得算法可以獨(dú)立于使用它的客戶而變化,也就是說這些算法所完成的功能是一樣的,對(duì)外接口是一樣的,只是各自現(xiàn)實(shí)上存在差異。
? ? 主要解決:在有多種算法相似的情況下,使用 if...else 所帶來的復(fù)雜和難以維護(hù)。
?? ?何時(shí)使用:一個(gè)系統(tǒng)有許多許多類,而區(qū)分它們的只是他們直接的行為,比如說A產(chǎn)品類的加法和減法與B產(chǎn)品的加法減法算? ? ? ? ? ? ? ? ? ? ? ? 法不一樣。
?? ?如何解決:將這些算法封裝成一個(gè)一個(gè)的類,任意地替換。
?? ?關(guān)鍵代碼:實(shí)現(xiàn)同一個(gè)接口。
?? ?缺點(diǎn): 1、策略類會(huì)增多。 2、所有策略類都需要對(duì)外暴露。
#include "iostream"
using namespace std;class Strategy
{
public:virtual void Algorithm() = 0;
};class ConcreteStrategyA : public Strategy
{void Algorithm(){cout << "算法A實(shí)現(xiàn)" << endl;}
};class ConcreteStrategyB : public Strategy
{void Algorithm(){cout << "算法B實(shí)現(xiàn)" << endl;}
};class ConcreteStrategyC : public Strategy
{void Algorithm(){cout << "算法C實(shí)現(xiàn)" << endl;}
};
//上下文
class Context
{
private:Strategy *strategy;
public:Context(Strategy *strategy){this->strategy = strategy;}void ContextAlgothrim(){this->strategy->Algorithm();}
};int _tmain(int argc, _TCHAR* argv[])
{Context *context;//Acontext = new Context(new ConcreteStrategyA());context->ContextAlgothrim();//Bcontext = new Context(new ConcreteStrategyB());context->ContextAlgothrim();//Ccontext = new Context(new ConcreteStrategyC());context->ContextAlgothrim();return 0;
}
3、適配器模式:將一個(gè)類的接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,使得原本由于接口不兼容而不能一起工作的哪些類可以一起工作。
適配器模式有三種:1.類的適配器 2.對(duì)象適配器 3.缺省適配器
? ? 示例:比如你在網(wǎng)上買了一個(gè)手機(jī),但是買家給你發(fā)回來了一個(gè)3接頭的充電器,但是恰好你又沒有3接頭的插槽,只有2個(gè)接口的插槽,于是你很直然地便會(huì)想到去找你個(gè)3接口轉(zhuǎn)兩接口的轉(zhuǎn)換器。簡單的分析下這個(gè)轉(zhuǎn)換器便是我們這里的適配器Adapter。三相插頭便是我們要適配的Adaptee
1.類的適配器
當(dāng)客戶在接口中定義了他期望的行為時(shí),我們就可以應(yīng)用適配器模式,提供一個(gè)實(shí)現(xiàn)該接口的類,并且擴(kuò)展已有的類,通過創(chuàng)建子類來實(shí)現(xiàn)適配。
#include "iostream"
using namespace std;//這是你的三相插頭
class ThreePhaseOutlet
{
public:void doThreePhasePlugin(){cout << "三相插頭強(qiáng)勢插入!" << endl;}
};//這是你想要的兩相插頭
class TwoPhaseOutlet
{
public:virtual void doPlugin() = 0;
};//然后你將需要找到一個(gè)轉(zhuǎn)接頭,將三相插頭轉(zhuǎn)換為“兩相插頭
class OutletConvertor : public TwoPhaseOutlet, public ThreePhaseOutlet
{
public:void doPlugin(){doConvertor();doThreePhasePlugin();}void doConvertor(){cout << "三相插頭轉(zhuǎn)為兩廂插頭!" << endl;}
};int _tmain(int argc, _TCHAR* argv[])
{TwoPhaseOutlet* outlet = new OutletConvertor();outlet->doPlugin();return 0;
}
2.對(duì)象適配器
對(duì)象適配器”通過組合除了滿足“用戶期待接口”還降低了代碼間的不良耦合。在工作中推薦使用“對(duì)象適配”。
#include "iostream"
using namespace std;//這是你的三相插頭
class ThreePhaseOutlet
{
public:void doThreePhasePlugin(){cout << "三相插頭強(qiáng)勢插入!" << endl;}
};//這是你想要的兩相插頭
class TwoPhaseOutlet
{
public:virtual void doPlugin() = 0;
};//對(duì)象適配器相比類適配器來說更加靈活,他可以選擇性適配自己想適配的對(duì)象。例如我們下面把代碼改成這樣,你也許就會(huì)明白為什么我這樣說:
class OutletConvertor : public TwoPhaseOutlet
{
public:OutletConvertor(){m_out = new ThreePhaseOutlet;}void doPlugin(){doConvertor();m_out->doThreePhasePlugin();}void doConvertor(){cout << "三相插頭轉(zhuǎn)為兩廂插頭!" << endl;}public:ThreePhaseOutlet *m_out;
};int _tmain(int argc, _TCHAR* argv[])
{TwoPhaseOutlet *outlet = new OutletConvertor();outlet->doPlugin();return 0;
}
3.缺省適配器
缺省適配器模式是一種特殊的適配器模式,但這個(gè)適配器是由一個(gè)抽象類實(shí)現(xiàn)的,并且在抽象類中要實(shí)現(xiàn)目標(biāo)接口中所規(guī)定的所有方法,但很多方法的實(shí)現(xiàn)都是“平庸”的實(shí)現(xiàn),也就是說,這些方法都是空方法。而具體的子類都要繼承此抽象類。
#include "iostream"
using namespace std;class Target {
public:virtual void f1(){};virtual void f2(){};virtual void f3(){};
};
class DefaultAdapter : public Target
{
public:void f1() {}void f2() {}void f3() {}
};
class MyInteresting :public DefaultAdapter
{
public:void f3(){cout << "呵呵,我就對(duì)f3()方法感興趣,別的不管了!" << endl;}
};int _tmain(int argc, _TCHAR* argv[])
{// Create adapter and place a requestTarget *t = new MyInteresting();t->f3();return 0;
}
*4. 單例模式(推薦:1為普通單例,3為多線程)
? ? 單例模式:保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。
?? ?主要解決:一個(gè)全局使用的類頻繁地創(chuàng)建與銷毀。
?? ?何時(shí)使用:想控制實(shí)例數(shù)目,節(jié)省系統(tǒng)資源的時(shí)候。
?? ?如何解決:判斷系統(tǒng)是否已存在單例,如果有則返回,沒有則創(chuàng)建。
?? ?關(guān)鍵代碼:構(gòu)造函數(shù)是私有的。
單例大約有兩種實(shí)現(xiàn)方法:懶漢與餓漢。
??? 懶漢:故名思義,不到萬不得已就不會(huì)去實(shí)例化類,也就是說在第一次用到類實(shí)例的時(shí)候才會(huì)去實(shí)例化,所以上邊的經(jīng)典方法? ? ? ? ? ? ? ? 被歸為懶漢實(shí)現(xiàn);
??? 餓漢:餓了肯定要饑不擇食。所以在單例類定義的時(shí)候就進(jìn)行實(shí)例化。
特點(diǎn)與選擇:
??? 由于要進(jìn)行線程同步,所以在訪問量比較大,或者可能訪問的線程比較多時(shí),采用餓漢實(shí)現(xiàn),可以實(shí)現(xiàn)更好的性能。這是以空? ? ? 間換時(shí)間。
??? 在訪問量較小時(shí),采用懶漢實(shí)現(xiàn)。這是以時(shí)間換空間。
1.懶漢式一般實(shí)現(xiàn):非線程安全,GetInstance返回的實(shí)例指針需要delete
#include "iostream"
using namespace std;class Singleton
{
public:static Singleton* GetInstance();~Singleton(){}int add(int a, int b){return a + b;}
private:static Singleton* m_pSingleton;Singleton(){}Singleton(const Singleton& obj) = delete; //明確拒絕Singleton& operator=(const Singleton& obj) = delete; //明確拒絕
};Singleton* Singleton::m_pSingleton = NULL;Singleton* Singleton::GetInstance()
{if (m_pSingleton == NULL){m_pSingleton = new Singleton;}return m_pSingleton;
}int _tmain(int argc, _TCHAR* argv[])
{Singleton* p = Singleton::GetInstance();printf("%d\n", p->add(1, 2));return 0;
}
構(gòu)造帶參數(shù)
.h
#ifndef _LOG_H_
#define _LOG_H_/**********************************************************************
* 版權(quán)所有 (C)2015, Zhao Yun。
*
* 文件名稱:log.cpp
* 文件標(biāo)識(shí):無
* 內(nèi)容摘要:演示日志信息的打印方法
* 其它說明:無
* 當(dāng)前版本:V1.0
* 作 者:Zhao Yun
* 完成日期:20150522
*
* **********************************************************************/
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include "global.h"// 日志級(jí)別定義
#define LOG_FATAL 0 // 嚴(yán)重錯(cuò)誤
#define LOG_ERROR 1 // 一般錯(cuò)誤
#define LOG_WARN 2 // 警告
#define LOG_INFO 3 // 一般信息
#define LOG_TRACE 4 // 跟蹤信息
#define LOG_DEBUG 5 // 調(diào)試信息
#define LOG_ALL 6 // 所有信息class LogOperation
{
public:static LogOperation* GetInstance(char* config_path);virtual ~LogOperation();//將內(nèi)容寫到日志文件中void WriteLogFile(int iLogLevel, const char *pszContent, const char *pszFileName = __FILE__, const char *pszFunctionName = __FUNCTION__, const int iCodeLine = __LINE__);//設(shè)置日志路徑void SetLogFilePath();//從配置文件中獲取字符串void GetConfigFileStringValue(const char *pszSectionName, const char *pszKeyName, const char *pDefaultVal, char *pszOutput, int iOutputLen, const char *pszConfigFileName);//從配置文件中獲取整型變量int GetConfigFileIntValue(const char *pszSectionName, const char *pszKeyName, int iDefaultVal, const char *pszConfigFileName);private:LogOperation(char* log_path);//獲取時(shí)間串void GetTime(char *pszTimeStr);//獲取對(duì)應(yīng)的日志等級(jí)const char *LogLevel(const int iLogLevel);//獲取具體的字符串值void GetStringContentValue(FILE *fp, const char *pszSectionName, const char *pszKeyName, char *pszOutput, int iOutputLen);private:static LogOperation* m_plogoperation;int g_iLogPosition; //在日志信息中顯示"文件名/函數(shù)名/代碼行數(shù)"信息 1為寫int g_iLogLevel; //日志等級(jí)char *g_sConfigureFilePath; //配置文件路徑char g_sLogFilePath[512]; //日志文件路徑
};#endif
?.cpp
/**********************************************************************
* 功能描述: 單例模式
* 輸入?yún)?shù): 無
* 輸出參數(shù): 無
* 返 回 值: 無
* 其它說明: 無
* 修改日期 版本號(hào) 修改人 修改內(nèi)容
* -------------------------------------------------------------------
* 20150522 V1.0 Zhao Yun 創(chuàng)建
********************************************************************/
LogOperation *LogOperation::m_plogoperation = NULL;LogOperation *LogOperation::GetInstance(char* config_path)
{if (m_plogoperation == NULL){m_plogoperation = new LogOperation(config_path);}return m_plogoperation;
}/**********************************************************************
* 功能描述: 構(gòu)造函數(shù)
* 輸入?yún)?shù): 無
* 輸出參數(shù): 無
* 返 回 值: 無
* 其它說明: 無
* 修改日期 版本號(hào) 修改人 修改內(nèi)容
* -------------------------------------------------------------------
* 20150522 V1.0 Zhao Yun 創(chuàng)建
********************************************************************/
LogOperation::LogOperation(char* log_path)
{//獲取路徑g_sConfigureFilePath = log_path;printf ("g_sConfigureFilePath = %s\n", g_sConfigureFilePath);//在日志信息中顯示"文件名/函數(shù)名/代碼行數(shù)"信息 1為寫g_iLogPosition = 1;// 日志等級(jí)g_iLogLevel = GetConfigFileIntValue("LOG", "LogLevel", 5, g_sConfigureFilePath);printf ("g_iLogLevel = %d\n", g_iLogLevel);//設(shè)置日志路徑GetConfigFileStringValue("LOG", "LogFilePath", NULL, g_sLogFilePath, 512-1, g_sConfigureFilePath);printf ("g_sLogFilePath = %s\n", g_sLogFilePath);
}/**********************************************************************
* 功能描述: 析構(gòu)函數(shù)
* 輸入?yún)?shù): 無
* 輸出參數(shù): 無
* 返 回 值: 無
* 其它說明: 無
* 修改日期 版本號(hào) 修改人 修改內(nèi)容
* -------------------------------------------------------------------
* 20150522 V1.0 Zhao Yun 創(chuàng)建
********************************************************************/
LogOperation::~LogOperation()
{delete m_plogoperation;
}
main.cpp
LogOperation *log = LogOperation::GetInstance(spLogFilePath);// 先打印版本相關(guān)信息snprintf(szLogContent, sizeof(szLogContent)-1, "Version [1.0], Build time[%s %s].", __DATE__, __TIME__);log->WriteLogFile(LOG_INFO, szLogContent);
?
2.懶漢式加鎖lock,線程安全
std::mutex mt;class Singleton
{
public:static Singleton* getInstance();
private:Singleton(){}Singleton(const Singleton&) = delete; //明確拒絕Singleton& operator=(const Singleton&) = delete; //明確拒絕static Singleton* m_pSingleton;};
Singleton* Singleton::m_pSingleton = NULL;Singleton* Singleton::getInstance()
{if(m_pSingleton == NULL){mt.lock();m_pSingleton = new Singleton();mt.unlock();}return m_pSingleton;
}
3. 惡漢模式:線程安全,注意delete
class Singleton
{
public:static Singleton* GetInstance();int add(int a, int b){return a + b;}
private:Singleton(){}Singleton(const Singleton&) = delete; //明確拒絕Singleton& operator=(const Singleton&) = delete; //明確拒絕static Singleton* m_pSingleton;
};Singleton* Singleton::m_pSingleton = new Singleton();Singleton* Singleton::GetInstance()
{return m_pSingleton;
}int _tmain(int argc, _TCHAR* argv[])
{Singleton* p = Singleton::GetInstance();printf("%d\n", p->add(1, 2));return 0;
}
5、原型模式:用原型實(shí)例指定創(chuàng)建對(duì)象的種類,并且通過拷貝這些原型創(chuàng)建新的對(duì)象。
? ? 主要解決:在運(yùn)行期建立和刪除對(duì)象。
?? ?何時(shí)使用:1).當(dāng)我們的對(duì)象類型不是開始就能確定的,而這個(gè)類型是在運(yùn)行期確定的話,那么我們通過這個(gè)類型的對(duì)象克隆出一個(gè)新的對(duì)象比較容易一些;2).有的時(shí)候,我們需要一個(gè)對(duì)象在某個(gè)狀態(tài)下的副本,此時(shí),我們使用原型模式是最好的選擇;例如:一個(gè)對(duì)象,經(jīng)過一段處理之后,其內(nèi)部的狀態(tài)發(fā)生了變化;這個(gè)時(shí)候,我們需要一個(gè)這個(gè)狀態(tài)的副本,如果直接new一個(gè)新的對(duì)象的話,但是它的狀態(tài)是不對(duì)的,此時(shí),可以使用原型模式,將原來的對(duì)象拷貝一個(gè)出來,這個(gè)對(duì)象就和之前的對(duì)象是完全一致的了;3).當(dāng)我們處理一些比較簡單的對(duì)象時(shí),并且對(duì)象之間的區(qū)別很小,可能就幾個(gè)屬性不同而已,那么就可以使用原型模式來完成,省去了創(chuàng)建對(duì)象時(shí)的麻煩了;4).有的時(shí)候,創(chuàng)建對(duì)象時(shí),構(gòu)造函數(shù)的參數(shù)很多,而自己又不完全的知道每個(gè)參數(shù)的意義,就可以使用原型模式來創(chuàng)建一個(gè)新的對(duì)象,不必去理會(huì)創(chuàng)建的過程。
?? ?->適當(dāng)?shù)臅r(shí)候考慮一下原型模式,能減少對(duì)應(yīng)的工作量,減少程序的復(fù)雜度,提高效率
?? ?如何解決:利用已有的一個(gè)原型對(duì)象,快速地生成和原型對(duì)象一樣的實(shí)例。
?? ?關(guān)鍵代碼:拷貝,return new className(*this);
class Clone
{
public:Clone(){}virtual ~Clone(){}virtual Clone* clone() = 0;virtual void show() = 0;
};class Sheep:public Clone
{
public:Sheep(int id, string name):Clone(),m_id(id),m_name(name){cout << "Sheep() id add:" << &m_id << endl;cout << "Sheep() name add:" << &m_name << endl;}~Sheep(){}Sheep(const Sheep& obj){this->m_id = obj.m_id;this->m_name = obj.m_name;cout << "Sheep(const Sheep& obj) id add:" << &m_id << endl;cout << "Sheep(const Sheep& obj) name add:" << &m_name << endl;}Clone* clone(){return new Sheep(*this);}void show(){cout << "id :" << m_id << endl;cout << "name:" << m_name.data() << endl;}
private:int m_id;string m_name;
};int main()
{Clone* s1 = new Sheep(1, "abs");s1->show();Clone* s2 = s1->clone();s2->show();delete s1;delete s2;return 0;
}
*6、模板模式:定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟。
? ? 主要解決:多個(gè)子類有相同的方法,并且邏輯相同,細(xì)節(jié)有差異。
?? ?如何解決:對(duì)重要,復(fù)雜的算法,將核心算法設(shè)計(jì)為模板方法,周邊細(xì)節(jié)由子類實(shí)現(xiàn),重構(gòu)時(shí),經(jīng)常使用的方法,將相同的代碼抽象到父類,通過鉤子函數(shù)約束行為。
?? ?關(guān)鍵代碼:在抽象類實(shí)現(xiàn)通用接口,細(xì)節(jié)變化在子類實(shí)現(xiàn)。
?? ?缺點(diǎn):每一個(gè)不同的實(shí)現(xiàn)都需要一個(gè)子類來實(shí)現(xiàn),導(dǎo)致類的個(gè)數(shù)增加,使得系統(tǒng)更加龐大。
#include "iostream"
using namespace std;class Computer
{
public:void product(){installCpu();installRam();installGraphicsCard();}protected:virtual void installCpu() = 0;virtual void installRam() = 0;virtual void installGraphicsCard() = 0;};class ComputerA :public Computer
{
protected:void installCpu() override{cout << "ComputerA install Inter Core i5" << endl;}void installRam() override{cout << "ComputerA install 2G Ram" << endl;}void installGraphicsCard() override{cout << "ComputerA install Gtx940 GraphicsCard" << endl;}
};class ComputerB :public Computer
{
protected:void installCpu() override{cout << "ComputerB install Inter Core i7" << endl;}void installRam() override{cout << "ComputerB install 4G Ram" << endl;}void installGraphicsCard() override{cout << "ComputerB install Gtx960 GraphicsCard" << endl;}
};int _tmain(int argc, _TCHAR* argv[])
{ComputerA a;a.product();ComputerB b;b.product();return 0;
}
7、 建造者模式:將復(fù)雜對(duì)象的構(gòu)建和其表示分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示。
? ? 主要解決:一個(gè)復(fù)雜對(duì)象的創(chuàng)建工作,由各個(gè)部分的子對(duì)象用一定的算法構(gòu)成;由于需求變化,這個(gè)復(fù)雜對(duì)象的各個(gè)部分經(jīng)常? ? ? ? ? ? ? ? ? ? ? 面臨變化,但將它們組合在一起的算法卻相對(duì)穩(wěn)定。
?? ?如何解決:將變與不變分開
?? ?關(guān)鍵代碼:建造者:創(chuàng)建和提供實(shí)例,Director:管理建造出來的實(shí)例的依賴關(guān)系。。
?? ?缺點(diǎn):1、產(chǎn)品必須有共同點(diǎn),范圍有限制。 2、如內(nèi)部變化復(fù)雜,會(huì)有很多的建造類。
typedef enum
{type1,type2
}ProductType;class Product //產(chǎn)品
{
public:void setNum(int num);void setColor(string color);void setType(ProductType type);void showProduct();
private:int m_num;string m_color;ProductType m_type;};void Product::setNum(int num)
{m_num = num;
}void Product::setColor(string color)
{m_color = color;
}void Product::setType(ProductType type)
{m_type = type;
}void Product::showProduct()
{cout << "Product: " << endl;cout << "num : " << m_num << endl;cout << "color: " << m_color.data() << endl;cout << "type : " << m_type << endl;
}//建造者父類,定義接口
class Builder
{
public:Builder(){}virtual ~Builder(){}virtual void buildNum(int num) = 0;virtual void buildColor(string color) = 0;virtual void buildType(ProductType type) = 0;virtual void createProduct() = 0;virtual Product* getProduct() = 0;virtual void show() = 0;
};//建造者A
class BuilderA :public Builder
{
public:BuilderA(){}~BuilderA(){}void buildNum(int num) override;void buildColor(string color) override;void buildType(ProductType type) override;void createProduct() override;Product* getProduct() override;void show() override;
private:Product* m_product;
};void BuilderA::buildNum(int num)
{cout << "BuilderA build Num: " << num << endl;m_product->setNum(num);
}void BuilderA::buildColor(string color)
{cout << "BuilderA build color: " << color.data() << endl;m_product->setColor(color);
}void BuilderA::buildType(ProductType type)
{cout << "BuilderA build type: " << type << endl;m_product->setType(type);
}void BuilderA::createProduct()
{cout << "BuilderA CreateProduct: " << endl;m_product = new Product();
}Product* BuilderA::getProduct()
{return m_product;
}
void BuilderA::show()
{m_product->showProduct();
}//建造者B
class BuilderB :public Builder
{
public:BuilderB(){}~BuilderB(){}void buildNum(int num) override;void buildColor(string color) override;void buildType(ProductType type) override;void createProduct() override;Product* getProduct() override;void show() override;
private:Product* m_product;
};void BuilderB::buildNum(int num)
{cout << "BuilderB build Num: " << num << endl;m_product->setNum(num);
}void BuilderB::buildColor(string color)
{cout << "BuilderB build color: " << color.data() << endl;m_product->setColor(color);
}void BuilderB::buildType(ProductType type)
{cout << "BuilderB build type: " << type << endl;m_product->setType(type);
}void BuilderB::createProduct()
{cout << "BuilderB CreateProduct: " << endl;m_product = new Product();
}Product* BuilderB::getProduct()
{return m_product;
}
void BuilderB::show()
{m_product->showProduct();
}//管理類,負(fù)責(zé)安排構(gòu)造的具體過程
class Director
{
public:Director(Builder* builder) :m_builder(builder){}void construct(int num, string color, ProductType type){m_builder->createProduct();m_builder->buildNum(num);m_builder->buildColor(color);m_builder->buildType(type);}private:Builder* m_builder;
};
8、外觀模式:為子系統(tǒng)中的一組接口定義一個(gè)一致的界面,外觀模式提供了一個(gè)高層接口,這個(gè)接口使得這一子系統(tǒng)更加容易被使用;對(duì)于復(fù)雜的系統(tǒng),系統(tǒng)為客戶提供一個(gè)簡單的接口,把復(fù)雜的實(shí)現(xiàn)過程封裝起來,客戶不需要了解系統(tǒng)內(nèi)部的細(xì)節(jié)。
? ? 主要解決:客戶不需要了解系統(tǒng)內(nèi)部復(fù)雜的細(xì)節(jié),只需要一個(gè)接口;系統(tǒng)入口。
?? ?如何解決:客戶不直接與系統(tǒng)耦合,而是通過外觀類與系統(tǒng)耦合。
?? ?關(guān)鍵代碼:客戶與系統(tǒng)之間加一個(gè)外觀層,外觀層處理系統(tǒng)的調(diào)用關(guān)系、依賴關(guān)系等。
?? ?缺點(diǎn):需要修改時(shí)不易繼承、不易修改。
class Cpu
{
public:void productCpu(){cout << "Product Cpu" << endl;}
};class Ram
{
public:void productRam(){cout << "Product Ram" << endl;}
};class Graphics
{
public:void productGraphics(){cout << "Product Graphics" << endl;}
};class Computer
{
public:void productComputer(){Cpu cpu;cpu.productCpu();Ram ram;ram.productRam();Graphics graphics;graphics.productGraphics();}
};int _tmain(int argc, _TCHAR* argv[])
{//客戶直接調(diào)用computer生產(chǎn)函數(shù),無需關(guān)心具體部件的生產(chǎn)過程。也可直接單獨(dú)生產(chǎn)部件Computer computer;computer.productComputer();Cpu cpu;cpu.productCpu();return 0;
}
9、組合模式:將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu),組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。
? ? 主要解決:它在我們樹型結(jié)構(gòu)的問題中,模糊了簡單元素和復(fù)雜元素的概念,客戶程序可以像處理簡單元素一樣處理復(fù)雜元? ? ? ? ? ? ? ? ? ? ? ? ?素,從而使得客戶程序與復(fù)雜元素的內(nèi)部結(jié)構(gòu)解耦。
?? ?如何解決:樹枝和樹葉實(shí)現(xiàn)統(tǒng)一接口,樹枝內(nèi)部組合該接口。
?? ?關(guān)鍵代碼:樹枝內(nèi)部組合該接口,并且含有內(nèi)部屬性list,里面放Component。
#include "iostream"
#include "list"
#include <future>
using namespace std;class Company
{
public:Company(string name) :m_name(name){}virtual ~Company(){}virtual void add(Company* company) = 0;virtual void remove(string name) = 0;virtual void display(int depth) = 0;string getName(){return m_name;}protected:string m_name;
};//具體的公司
class ConcreteCompany :public Company //樹枝
{
public:ConcreteCompany(string name) :Company(name){}~ConcreteCompany(){cout << "~ConcreteCompany()" << endl;}void add(Company* company) override;void remove(string name) override;void display(int depth) override;private:list<shared_ptr<Company>> m_listCompany;};void ConcreteCompany::add(Company* company)
{shared_ptr<Company> temp(company);m_listCompany.push_back(temp);
}void ConcreteCompany::remove(string name)
{list<shared_ptr<Company>>::iterator iter = m_listCompany.begin();for (; iter != m_listCompany.end(); iter++){shared_ptr<Company> temp(*iter);string strName = temp.get()->getName();if (name == strName){m_listCompany.erase(iter);}}
}void ConcreteCompany::display(int depth)
{for (int i = 0; i < depth; i++){cout << "-";}cout << m_name.data() << endl;list<shared_ptr<Company>>::iterator iter = m_listCompany.begin();for (; iter != m_listCompany.end(); iter++){shared_ptr<Company> temp(*iter);temp.get()->display(depth + 2);}
}//公司下的部門
class FinanceDept :public Company //樹葉
{
public:FinanceDept(string name) :Company(name){}~FinanceDept(){cout << "~FinanceDept()" << endl;}void add(Company* company) override;void remove(string name) override;void display(int depth) override;
};void FinanceDept::add(Company* company)
{cout << "FinanceDept add failed" << endl;
}void FinanceDept::remove(string name)
{cout << "FinanceDept remove failed" << endl;
}void FinanceDept::display(int depth)
{for (int i = 0; i < depth; i++){cout << "-";}cout << m_name.data() << endl;
}//公司下的部門
class HRDept :public Company //樹葉
{
public:HRDept(string name) :Company(name){}~HRDept(){cout << "~HRDept()" << endl;}void add(Company* company) override;void remove(string name) override;void display(int depth) override;
};void HRDept::add(Company* company)
{cout << "HRDept add failed" << endl;
}void HRDept::remove(string name)
{cout << "HRDept remove failed" << endl;
}void HRDept::display(int depth)
{for (int i = 0; i < depth; i++){cout << "-";}cout << m_name.data() << endl;
}int _tmain(int argc, _TCHAR* argv[])
{Company* root = new ConcreteCompany("zong");Company* f1 = new FinanceDept("F1");Company* h1 = new HRDept("H1");root->add(f1);root->add(h1);Company* c1 = new ConcreteCompany("fen1");Company* f2 = new FinanceDept("F2");Company* h2 = new HRDept("H2");c1->add(f2);c1->add(h2);root->add(c1);root->display(0);delete root;return 0;
}
*10、 代理模式:為其它對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。
? ? 主要解決:在直接訪問對(duì)象時(shí)帶來的問題,比如:要訪問的對(duì)象在遠(yuǎn)程服務(wù)器上。在面向?qū)ο笙到y(tǒng)中,有些對(duì)象由于某些原? ? ? ? ? ? ? ? ? ? ? ? ? 因,直接訪問會(huì)給使用者或系統(tǒng)帶來很多麻煩,可以在訪問此對(duì)象時(shí)加上一個(gè)對(duì)此對(duì)象的訪問層。
?? ?如何解決:增加中間代理層。
?? ?關(guān)鍵代碼:實(shí)現(xiàn)與被代理類組合。
class Gril
{
public:Gril(string name = "gril") :m_string(name){}string getName(){return m_string;}
private:string m_string;
};class Profession
{
public:virtual ~Profession(){}virtual void profess() = 0;
};class YoungMan :public Profession
{
public:YoungMan(Gril gril) :m_gril(gril){}void profess(){cout << "Young man love " << m_gril.getName().data() << endl;}
private:Gril m_gril;
};class ManProxy :public Profession
{
public:ManProxy(Gril gril) :m_man(new YoungMan(gril)){}void profess(){cout << "I am Proxy" << endl;m_man->profess();}
private:YoungMan* m_man;
};int _tmain(int argc, _TCHAR* argv[])
{Gril gril("hei");Profession* proxy = new ManProxy(gril);proxy->profess();delete proxy;return 0;
}
11、享元模式:運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對(duì)象。
? ? 主要解決:在有大量對(duì)象時(shí),把其中共同的部分抽象出來,如果有相同的業(yè)務(wù)請(qǐng)求,直接返回內(nèi)存中已有的對(duì)象,避免重新創(chuàng)? ? ? ? ? ? ? ? ? ? ? ? 建。
?? ?如何解決:用唯一標(biāo)識(shí)碼判斷,如果內(nèi)存中有,則返回這個(gè)唯一標(biāo)識(shí)碼所標(biāo)識(shí)的對(duì)象。
?? ?關(guān)鍵代碼:將內(nèi)部狀態(tài)作為標(biāo)識(shí),進(jìn)行共享。
//以Money的類別作為內(nèi)部標(biāo)識(shí),面值作為外部狀態(tài)。
enum MoneyCategory //類別,內(nèi)在標(biāo)識(shí),作為標(biāo)識(shí)碼
{Coin,bankNote
};enum FaceValue //面值,外部標(biāo)識(shí),需要存儲(chǔ)的對(duì)象
{ValueOne = 1,ValueTwo
};class Money //抽象父類
{
public:Money(MoneyCategory cate):m_mCate(cate){}virtual ~Money(){ cout << "~Money() " << endl; }virtual void save() = 0;
private:MoneyCategory m_mCate;
};class MoneyCoin:public Money //具體子類1
{
public:MoneyCoin(MoneyCategory cate):Money(cate){}~MoneyCoin(){ cout << "~MoneyCoin()" << endl; }void save(){cout << "Save Coin" << endl;}
};class MoneyNote:public Money //具體子類2
{
public:MoneyNote(MoneyCategory cate):Money(cate){}~MoneyNote(){ cout << "~MoneyNote()" << endl; }void save(){cout << "Save BankNote" << endl;}
};class Bank
{
public:Bank():m_coin(nullptr),m_note(nullptr),m_count(0){}~Bank(){if(m_coin != nullptr){delete m_coin;m_coin = nullptr;}if(m_note != nullptr){delete m_note;m_note = nullptr;}}void saveMoney(MoneyCategory cate, FaceValue value){switch(cate) //以類別作為標(biāo)識(shí)碼{case Coin:{if(m_coin == nullptr) //內(nèi)存中存在標(biāo)識(shí)碼所標(biāo)識(shí)的對(duì)象,則直接調(diào)用,不再創(chuàng)建{m_coin = new MoneyCoin(Coin);}m_coin->save();m_vector.push_back(value);break;}case bankNote:{if(m_note == nullptr){m_note = new MoneyNote(bankNote);}m_note->save();m_vector.push_back(value);break;}default:break;}}int sumSave(){auto iter = m_vector.begin();for(; iter != m_vector.end(); iter++){m_count += *iter;}return m_count;}private:vector<FaceValue> m_vector;Money* m_coin;Money* m_note;int m_count;
};int main()
{Bank b1;b1.saveMoney(Coin, ValueOne);b1.saveMoney(Coin, ValueTwo);b1.saveMoney(Coin, ValueTwo);b1.saveMoney(bankNote, ValueOne);b1.saveMoney(bankNote, ValueTwo);cout << b1.sumSave() << endl;return 0;
}
12、 橋接模式:將抽象部分與實(shí)現(xiàn)部分分離,使它們都可以獨(dú)立變換。
? ? 主要解決:在有很多中可能會(huì)變化的情況下,用繼承會(huì)造成類爆炸問題,不易擴(kuò)展。
?? ?如何解決:把不同的分類分離出來,使它們獨(dú)立變化,減少它們之間的耦合。
?? ?關(guān)鍵代碼:將現(xiàn)實(shí)獨(dú)立出來,抽象類依賴現(xiàn)實(shí)類。
//將各種App、各種手機(jī)全部獨(dú)立分開,使其自由組合橋接
class App
{
public:virtual ~App(){ cout << "~App()" << endl; }virtual void run() = 0;
};class GameApp :public App
{
public:void run(){cout << "GameApp Running" << endl;}
};class TranslateApp :public App
{
public:void run(){cout << "TranslateApp Running" << endl;}
};class MobilePhone
{
public:virtual ~MobilePhone(){ cout << "~MobilePhone()" << endl; }virtual void appRun(App* app) = 0; //實(shí)現(xiàn)App與手機(jī)的橋接
};class XiaoMi :public MobilePhone
{
public:void appRun(App* app){cout << "XiaoMi: ";app->run();}
};class HuaWei :public MobilePhone
{
public:void appRun(App* app){cout << "HuaWei: ";app->run();}
};int _tmain(int argc, _TCHAR* argv[])
{App* gameApp = new GameApp;App* translateApp = new TranslateApp;MobilePhone* mi = new XiaoMi;MobilePhone* hua = new HuaWei;mi->appRun(gameApp);mi->appRun(translateApp);hua->appRun(gameApp);hua->appRun(translateApp);delete hua;delete mi;delete gameApp;delete translateApp;return 0;
}
13、 裝飾模式:動(dòng)態(tài)地給一個(gè)對(duì)象添加一些額外的功能,就新增加功能來說,裝飾器模式比生產(chǎn)子類更加靈活。
? ? 主要解決:通常我們?yōu)榱藬U(kuò)展一個(gè)類經(jīng)常使用繼承的方式,由于繼承為類引入靜態(tài)特征,并且隨著擴(kuò)展功能的增多,子類會(huì)很? ? ? ? ? ? ? ? ? ? ? ? 膨脹。
?? ?如何解決:將具體的功能劃分,同時(shí)繼承裝飾者類。
?? ?關(guān)鍵代碼:裝飾類復(fù)合和繼承組件類,具體的擴(kuò)展類重寫父類的方法。
class Dumplings //抽象類 餃子
{
public:virtual ~Dumplings(){}virtual void showDressing() = 0;
};class MeatDumplings :public Dumplings //現(xiàn)實(shí)類 肉餡餃子
{
public:~MeatDumplings(){ cout << "~MeatDumplings()" << endl; }void showDressing(){cout << "Add Meat" << endl;}
};class DecoratorDumpling :public Dumplings //裝飾類
{
public:DecoratorDumpling(Dumplings* d) :m_dumpling(d){}virtual ~DecoratorDumpling(){ cout << "~DecoratorDumpling()" << endl; }void showDressing(){m_dumpling->showDressing();}
private:Dumplings* m_dumpling;
};class SaltDecorator :public DecoratorDumpling // 裝飾類 加鹽
{
public:SaltDecorator(Dumplings* d) :DecoratorDumpling(d){}~SaltDecorator(){ cout << "~SaltDecorator()" << endl; }void showDressing(){DecoratorDumpling::showDressing(); //注意點(diǎn)addDressing();}private:void addDressing(){cout << "Add Salt" << endl;}
};class OilDecorator :public DecoratorDumpling //裝飾類 加油
{
public:OilDecorator(Dumplings* d) :DecoratorDumpling(d){}~OilDecorator(){ cout << "~OilDecorator()" << endl; }void showDressing(){DecoratorDumpling::showDressing(); //注意點(diǎn)addDressing();}private:void addDressing(){cout << "Add Oil" << endl;}
};class CabbageDecorator :public DecoratorDumpling //裝飾類 加蔬菜
{
public:CabbageDecorator(Dumplings* d) :DecoratorDumpling(d){}~CabbageDecorator(){ cout << "~CabbageDecorator()" << endl; }void showDressing(){DecoratorDumpling::showDressing(); //注意點(diǎn)addDressing();}private:void addDressing(){cout << "Add Cabbage" << endl;}
};int _tmain(int argc, _TCHAR* argv[])
{Dumplings* d = new MeatDumplings; //原始的肉餃子Dumplings* d1 = new SaltDecorator(d); //加鹽后的餃子Dumplings* d2 = new OilDecorator(d1); //加油后的餃子Dumplings* d3 = new CabbageDecorator(d2); //加蔬菜后的餃子d3->showDressing();delete d;delete d1;delete d2;delete d3;return 0;
}
*14、備忘錄模式:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。這樣以后就可以將該對(duì)象恢復(fù)到原來保存的狀態(tài)。
? ? 如何解決:通過一個(gè)備忘錄類專門存儲(chǔ)對(duì)象狀態(tài)。
?? ?關(guān)鍵代碼:備忘錄類、客戶類、備忘錄管理類;客戶類不與備忘錄類耦合,而是與備忘錄管理類耦合。
typedef struct //需要保存的信息
{int grade;string arm;string corps;
}GameValue;class Memento //備忘錄類
{
public:Memento(){}Memento(GameValue value) :m_gameValue(value){}GameValue getValue(){return m_gameValue;}
private:GameValue m_gameValue;
};class Game //客戶類 游戲
{
public:Game(GameValue value) :m_gameValue(value){}void addGrade() //等級(jí)增加{m_gameValue.grade++;}void replaceArm(string arm) //更換武器{m_gameValue.arm = arm;}void replaceCorps(string corps) //更換工會(huì){m_gameValue.corps = corps;}Memento saveValue() //保存當(dāng)前信息{Memento memento(m_gameValue);return memento;}void load(Memento memento) //載入信息{m_gameValue = memento.getValue();}void showValue(){cout << "Grade: " << m_gameValue.grade << endl;cout << "Arm : " << m_gameValue.arm.data() << endl;cout << "Corps: " << m_gameValue.corps.data() << endl;}
private:GameValue m_gameValue;
};class Caretake //備忘錄管理類
{
public:void save(Memento memento) //保存信息{m_memento = memento;}Memento load() //讀已保存的信息{return m_memento;}
private:Memento m_memento;
};int _tmain(int argc, _TCHAR* argv[])
{GameValue v1 = { 0, "Ak", "3K" };Game game(v1); //初始值game.addGrade();game.showValue();cout << "----------" << endl;Caretake care;care.save(game.saveValue()); //保存當(dāng)前值game.addGrade(); //修改當(dāng)前值game.replaceArm("M16");game.replaceCorps("123");game.showValue();cout << "----------" << endl;game.load(care.load()); //恢復(fù)初始值game.showValue();return 0;
}
15、中介者模式:用一個(gè)中介對(duì)象來封裝一系列的對(duì)象交互,中介者使各對(duì)象不需要顯示地相互引用,從而使其耦合松散,而且可以獨(dú)立地改變它們之前的交互。
? ? 主要解決:對(duì)象與對(duì)象之前存在大量的關(guān)聯(lián)關(guān)系,這樣勢必會(huì)造成系統(tǒng)變得復(fù)雜,若一個(gè)對(duì)象改變,我們常常需要跟蹤與之關(guān)? ? ? ? ? ? ? ? ? ? ? ? 聯(lián)的對(duì)象,并做出相應(yīng)的處理。
?? ?如何解決:將網(wǎng)狀結(jié)構(gòu)分離為星型結(jié)構(gòu)。
?? ?關(guān)鍵代碼:將相關(guān)對(duì)象的通信封裝到一個(gè)類中單獨(dú)處理。
class Mediator;class Person //抽象同事類
{
public:virtual ~Person(){}virtual void setMediator(Mediator* mediator){m_mediator = mediator;}virtual void sendMessage(const string& message) = 0;virtual void getMessage(const string& message) = 0;
protected:Mediator* m_mediator;
};class Mediator //抽象中介類
{
public:virtual ~Mediator(){}virtual void setBuyer(Person* buyer) = 0;virtual void setSeller(Person* seller) = 0;virtual void send(const string& message, Person* person) = 0;
};class Buyer :public Person //買家類
{
public:void sendMessage(const string& message){m_mediator->send(message, this);}void getMessage(const string& message){cout << "Buyer Get: " << message.data() << endl;}
};class Seller :public Person //賣家類
{
public:void sendMessage(const string& message){m_mediator->send(message, this);}void getMessage(const string& message){cout << "Seller Get: " << message.data() << endl;}
};class HouseMediator :public Mediator //具體的中介類
{
public:HouseMediator() :m_buyer(nullptr), m_seller(nullptr){}void setBuyer(Person* buyer){m_buyer = buyer;}void setSeller(Person *seller){m_seller = seller;}void send(const string& message, Person* person){if (person == m_buyer){m_seller->getMessage(message);}if (person == m_seller){m_buyer->getMessage(message);}}
private:Person* m_buyer;Person* m_seller;
};int _tmain(int argc, _TCHAR* argv[])
{Person* buyer = new Buyer;Person* seller = new Seller;Mediator* houseMediator = new HouseMediator;buyer->setMediator(houseMediator);seller->setMediator(houseMediator);houseMediator->setBuyer(buyer);houseMediator->setSeller(seller);buyer->sendMessage("1.5?");seller->sendMessage("2!!!");return 0;
}
*16、職責(zé)鏈模式:使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之前的耦合關(guān)系,將這些對(duì)象連成一條鏈,并沿著這條鏈傳遞請(qǐng)求,直到有一個(gè)對(duì)象處理它為止。
? ? ?主要解決:職責(zé)鏈上的處理者負(fù)責(zé)處理請(qǐng)求,客戶只需要將請(qǐng)求發(fā)送到職責(zé)鏈上即可,無需關(guān)心請(qǐng)求的處理細(xì)節(jié)和請(qǐng)求的傳? ? ? ? ? ? ? ? ? ? ? ? ? ?遞,所有職責(zé)鏈將請(qǐng)求的發(fā)送者和請(qǐng)求的處理者解耦了。
?? ?如何解決:職責(zé)鏈鏈扣類都現(xiàn)實(shí)統(tǒng)一的接口。
?? ?關(guān)鍵代碼:Handler內(nèi)指明其上級(jí),handleRequest()里判斷是否合適,不合適則傳遞給上級(jí)。
enum RequestLevel
{One = 1,Two,Three
};class Leader
{
public:Leader(Leader* leader):m_leader(leader){}virtual ~Leader(){}virtual void handleRequest(RequestLevel level) = 0;
protected:Leader* m_leader;
};class Monitor:public Leader //鏈扣1
{
public:Monitor(Leader* leader):Leader(leader){}void handleRequest(RequestLevel level){if(level < Two){cout << "Mointor handle request : " << level << endl;}else{m_leader->handleRequest(level);}}
};class Captain:public Leader //鏈扣2
{
public:Captain(Leader* leader):Leader(leader){}void handleRequest(RequestLevel level){if(level < Three){cout << "Captain handle request : " << level << endl;}else{m_leader->handleRequest(level);}}
};class General:public Leader //鏈扣3
{
public:General(Leader* leader):Leader(leader){}void handleRequest(RequestLevel level){cout << "General handle request : " << level << endl;}
};int main()
{Leader* general = new General(nullptr);Leader* captain = new Captain(general);Leader* monitor = new Monitor(captain);monitor->handleRequest(Two);return 0;
}
*17、觀察者模式:定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都要得到通知并自動(dòng)更新。
? ? 主要解決:一個(gè)對(duì)象更新,其它對(duì)象也要更新。
?? ?如何解決:目標(biāo)類通知函數(shù)通知所有觀察者自動(dòng)更新。
?? ?關(guān)鍵代碼:在目標(biāo)類中增加一個(gè)ArrayList來存放觀察者們。
#include "iostream"
#include "list"
//#include <future>
using namespace std;//數(shù)據(jù)模型為目標(biāo)類,視圖為觀察者類。當(dāng)數(shù)據(jù)模型發(fā)生改變時(shí),通知視圖類更新
class View;class DataModel //目標(biāo)抽象類 數(shù)據(jù)模型
{
public:virtual ~DataModel(){}virtual void add(View* view) = 0;virtual void remove(View* view) = 0;virtual void notify() = 0; //通知函數(shù)
};class View //觀察者抽象類 視圖
{
public:virtual ~View(){ cout << "~View()" << endl; }virtual void update() = 0;
};class IntModel :public DataModel //具體的目標(biāo)類, 整數(shù)模型
{
public:~IntModel(){clear();}void add(View* view){auto iter = std::find(m_list.begin(), m_list.end(), view); //判斷是否重復(fù)添加if (iter == m_list.end()){m_list.push_back(view);}}void remove(View* view){auto iter = m_list.begin();for (; iter != m_list.end(); iter++){if (*iter == view){delete *iter; //釋放內(nèi)存m_list.erase(iter); //刪除元素break;}}}void notify() //通知觀察者更新{auto iter = m_list.begin();for (; iter != m_list.end(); iter++){(*iter)->update();}}
private:void clear(){if (!m_list.empty()){auto iter = m_list.begin();for (; iter != m_list.end(); iter++) //釋放內(nèi)存{delete *iter;}}}
private:list<View*> m_list;
};class TreeView :public View //具體的觀察者類 視圖
{
public:TreeView(string name) :m_name(name), View(){}~TreeView(){ cout << "~TreeView()" << endl; }void update(){cout << m_name.data() << " : Update" << endl;}
private:string m_name;
};int _tmain(int argc, _TCHAR* argv[])
{View* v1 = new TreeView("view1");View* v2 = new TreeView("view2");View* v3 = new TreeView("view3");View* v4 = new TreeView("view4");DataModel* model = new IntModel;model->add(v1);model->add(v2);model->add(v3);model->add(v2);model->add(v4);model->notify();cout << "----------" << endl;model->remove(v2);model->notify();delete model;return 0;
}
?
總結(jié)
以上是生活随笔為你收集整理的C++ 常用设计模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。