1.單例模式
作用:保證一個類只有一個實例,并提供一個訪問它的全局訪問點,使得系統(tǒng)中只有唯一的一個對象實例。
應(yīng)用:常用于管理資源,如日志、線程池
實現(xiàn)要點:
在類中,要構(gòu)造一個實例,就必須調(diào)用類的構(gòu)造函數(shù),并且為了保證全局只有一個實例,
需防止在外部調(diào)用類的構(gòu)造函數(shù)而構(gòu)造實例,需要將構(gòu)造函數(shù)的訪問權(quán)限標(biāo)記為private,
同時阻止拷貝創(chuàng)建對象時賦值時拷貝對象,因此也將它們聲明并權(quán)限標(biāo)記為private;
另外,需要提供一個全局訪問點,就需要在類中定義一個static函數(shù),返回在類內(nèi)部唯一構(gòu)造的實例。
class Singleton{
public:
static Singleton& getInstance(){
static Singleton instance;
return instance;
}
void printTest(){
cout< "do something"<
首先,構(gòu)造函數(shù)聲明成private的目的是只允許內(nèi)部調(diào)用,getInstance()中的靜態(tài)局部變量創(chuàng)建時調(diào)用,但不允許外部調(diào)用構(gòu)造創(chuàng)建第二個實例;
然后,拷貝構(gòu)造和拷貝賦值符是聲明成了private而不給出定義,其目的是阻止拷貝,如果企圖通過拷貝構(gòu)造來創(chuàng)建第二個實例,編譯器會報錯。
阻止拷貝的另一種寫法是聲明后接一個"=delete",也能起到相同的作用(C++11)。
2.工廠模式
工廠模式包括三種:簡單工廠模式、工廠方法模式、抽象工廠模式。
工廠模式的主要作用是封裝對象的創(chuàng)建,分離對象的創(chuàng)建和操作過程,用于批量管理對象的創(chuàng)建過程,便于程序的維護(hù)和擴展。
(1)簡單工廠模式
簡單工廠是工廠模式最簡單的一種實現(xiàn),對于不同產(chǎn)品的創(chuàng)建定義一個工廠類,將產(chǎn)品的類型作為參數(shù)傳入到工廠的創(chuàng)建函數(shù),根據(jù)類型分支選擇不同的產(chǎn)品構(gòu)造函數(shù)。
//簡單工廠模式
typedef enum ProductTypeTag
{
TypeA,
TypeB,
TypeC
}PRODUCTTYPE;
class Product//產(chǎn)品抽象基類
{
public:
virtual void Show() = 0;
};
class ProductA : public Product
{
public:
void Show()
{
cout< "I'm ProductA"<
(2)工廠方法模式
其實這才是正宗的工廠模式,簡單工廠模式只是一個簡單的對創(chuàng)建過程封裝。工廠方法模式在簡單工廠模式的基礎(chǔ)上增加對工廠的基類抽象,不同的產(chǎn)品創(chuàng)建采用不同的工廠創(chuàng)建(從工廠的抽象基類派生),這樣創(chuàng)建不同的產(chǎn)品過程就由不同的工廠分工解決:FactoryA專心負(fù)責(zé)生產(chǎn)ProductA,F(xiàn)actoryB專心負(fù)責(zé)生產(chǎn)ProductB,F(xiàn)actoryA和FactoryB之間沒有關(guān)系;如果到了后期,如果需要生產(chǎn)ProductC時,我們則可以創(chuàng)建一個FactoryC工廠類,該類專心負(fù)責(zé)生產(chǎn)ProductC類產(chǎn)品。
該模式相對于簡單工廠模式的優(yōu)勢在于:便于后期產(chǎn)品種類的擴展。
//工廠方法模式
typedef enum ProductTypeTag
{
TypeA,
TypeB,
TypeC
}PRODUCTTYPE;
class Product//產(chǎn)品抽象基類
{
public:
virtual void Show() = 0;
};
class ProductA : public Product
{
public:
void Show()
{
cout< "I'm ProductA"<
(3)抽象工廠模式
抽象工廠模式對工廠方法模式進(jìn)行了更加一般化的描述。工廠方法模式適用于產(chǎn)品種類結(jié)構(gòu)單一的場合,為一類產(chǎn)品提供創(chuàng)建的接口;而抽象工廠方法適用于產(chǎn)品種類結(jié)構(gòu)多的場合,就是當(dāng)具有多個抽象產(chǎn)品類型時,抽象工廠便可以派上用場。
抽象工廠模式更適合實際情況,受生產(chǎn)線所限,讓低端工廠生產(chǎn)不同種類的低端產(chǎn)品,高端工廠生產(chǎn)不同種類的高端產(chǎn)品。
//抽象工廠模式
class ProductA
{
public:
virtual void Show() = 0;
};
class ProductA1 : public ProductA//A類低端產(chǎn)品
{
public:
void Show()
{
cout< "I'm ProductA1"<
3 策略模式
策略模式也是一種非常常用的設(shè)計模式,而且也不復(fù)雜。下面我們就來看看這種模式。
定義:策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。
角色:
抽象策略角色(Strategy):抽象策略類。
具體策略角色(ConcreteStrategy):封裝了繼續(xù)相關(guān)的算法和行為。
環(huán)境角色(Context):持有一個策略類的引用,最終給客戶端調(diào)用。
UML圖:
事例:(該事例改編自一道網(wǎng)絡(luò)設(shè)計模式面試題)
如現(xiàn)在你是一個設(shè)計師,你正在設(shè)計一種空調(diào)。但是你們的空調(diào)要支持3種模式。冷風(fēng)模式(ColdWind), 熱風(fēng)模式(WramWind),無風(fēng)模式(NoWind)。
當(dāng)選擇ColdWind模式,將輸送冷風(fēng);當(dāng)選擇WarmWind模式,將輸送熱風(fēng);在選擇NoWind模式時,空調(diào)什么都不做。你將考慮如何為空調(diào)設(shè)計應(yīng)用程序?如果將來空調(diào)需要增加支持新的模式呢?
這道面試題,其實可以用各種模式實現(xiàn),然而在這里我理解策略模式比較合適。我們將冷風(fēng)模式,和熱風(fēng)模式以及無風(fēng)模式可以理解為各種不同的算法。顯然策略模式非常符合。
這里ColdWind, WramWind, NoWind 其實就是ConcreteStrategy。IWnd 是抽象策略類。所以我們開始這么封裝我們策略類
#include < iostream >
using namespace std;
#define free_ptr(p)
if(p) delete p; p = NULL;
class IWind{
public:
virtual ~IWind(){};
virtual void blowWind() = 0;
};
class ColdWind : public IWind{
public:
void blowWind(){
cout< "Blowing cold wind!"<
然后我們實現(xiàn)一個windmode 的類,作為 wind 系列的環(huán)境類:
class WindMode{
public:
WindMode(IWind* wind): m_wind(wind){};
~WindMode(){free_ptr(m_wind);}
void blowWind(){
m_wind- >blowWind();
};
private:
IWind* m_wind;
};
最后客戶端代碼:
int main(int argc, char* argv[])
{
WindMode* warmWind = new WindMode(new WarmWind());
WindMode* coldWind = new WindMode(new ColdWind());
WindMode* noWind = new WindMode(new NoWind());
warmWind- >BlowWind();
coldWind- >BlowWind();
noWind- >BlowWind();
free_ptr(warmWind);
free_ptr(coldWind);
free_ptr(noWind);
system("pause");
return 0;
}
(這個實例網(wǎng)上也有人用命令模式實現(xiàn)。命令模式請看我后面的博客。把冷風(fēng),熱風(fēng),無風(fēng)作為一種命令。當(dāng)然這是另外一種思路,也未嘗不可。但是我覺得如果采用命令模式。類的個數(shù)會相應(yīng)增加(增加系列的命令類),造成額外的開銷。當(dāng)添加一個新模式的時候,你需要添加的類過多。或多或少不是那么明智。所以我個人認(rèn)為在這里策略模式更好一些。)
總的說來策略模式:
優(yōu)點:
1、 使用策略模式可以避免使用多重條件轉(zhuǎn)移語句。多重轉(zhuǎn)移語句不易維護(hù)。
2、 策略模式讓你可以動態(tài)的改變對象的行為,動態(tài)修改策略
缺點:
1、客戶端必須知道所有的策略類,并自行決定使用哪一個策略類。
2、類過多---策略模式造成很多的策略類,每個具體策略類都會產(chǎn)生一個新類。(這點可以通過享元模式來克服類過多)
模式定義:
命令模式將“請求”封裝成對象,以便使用不同的請求、隊列或者日志來參數(shù)化其他對象。命令模式也支持可撤銷的操作。
命令對象將動作和接受者包進(jìn)對象中,這個對象只暴露一個execute()方法。
當(dāng)需要將發(fā)出請求的對象和執(zhí)行請求的對象解耦的時候,使用命令模式。
模式結(jié)構(gòu):
舉例:
遙控器上有一個插槽,可以放上不同的裝置,然后用按鈕控制。我們這里放置電燈,并有開和關(guān)按鈕??梢悦钅J綄崿F(xiàn)。
UML設(shè)計:
其中,RemoteControl為遙控器,LightOnCommand為開燈請求對象,LightOffCommand為關(guān)燈請求對象,他們繼承自基類Command,這樣設(shè)計可以使插槽在以后防止其他的裝置。
#include < iostream >
using namespace std;
//電燈類
class Light
{
public:
void on()
{
cout < < "Light on !" < < endl;
}
void off()
{
cout < < "Light off !" < < endl;
}
};
//命令類
class Command
{
public:
virtual void execute(){}
};
//具體命令類
class LigthOnCommand : public Command
{
public:
LigthOnCommand(Light* lig):light(lig){}
//execute方法
void execute()
{
light- >on();
}
private:
Light* light;
};
class LigthOffCommand : public Command
{
public:
LigthOffCommand(Light* lig):light(lig){}
void execute()
{
light- >off();
}
private:
Light* light;
};
//遙控器類
class RemoteControl
{
public:
void setCommand(Command* command)
{
slot = command;
}
void buttonOn()
{
slot- >execute();
}
private:
Command* slot;
};
//客戶代碼
int main()
{
RemoteControl lightOnControl;
RemoteControl lightOffControl;
Command* onCommand = new LigthOnCommand(new Light());
Command* offCommand = new LigthOffCommand(new Light());
lightOnControl.setCommand(onCommand);
lightOffControl.setCommand(offCommand);
lightOnControl.buttonOn();
lightOffControl.buttonOn();
return 0;
}
執(zhí)行結(jié)果:
Lighton !
Lightoff !
請按任意鍵繼續(xù). .
-
函數(shù)
+關(guān)注
關(guān)注
3文章
4350瀏覽量
63069 -
編譯器
+關(guān)注
關(guān)注
1文章
1643瀏覽量
49345 -
日志
+關(guān)注
關(guān)注
0文章
139瀏覽量
10690 -
設(shè)計模式
+關(guān)注
關(guān)注
0文章
53瀏覽量
8657
發(fā)布評論請先 登錄
相關(guān)推薦
評論