標籤:

人工智慧——Singleton模式

上次在狀態模式中的設計有一個嚴重的問題,就是如下:

void CTroll::ChageState(CState* pNewState)

{

delete m_pCurrentState;

m_pCurrentState=pNewState;

Update();

}

在狀態切換中不斷有內存申請、刪除的操作,如果智能體狀態切換頻繁,會非常消耗時間。要解決這個問題,就要用到Singleton模式。

Singleton模式有多種實現方法,其核心就是把類構造函數私有化,使得外部不能實例化該類。然後在類內部用一個全局的靜態函數來完成類的實例化,用一個靜態變數保存唯一實例地址。但為了解決線程安全問題,Scott Meyers在《Effective C++》(Item 04)中提出一種更優雅的單例模式實現,使用local static對象(C++中的static對象是指存儲區不屬於stack和heap、"壽命"從被構造出來直至程序結束為止的對象。其中,函數內的static對象稱為local static 對象,而其它static對象稱為non-local static對象。對於local static對象,在其所屬的函數被調用之前,該對象並不存在,即只有在第一次調用對應函數時,local static對象才被構造出來。)比如以下代碼:

class CState_Runaway:public CState

{

private: //構造函數,拷貝構造和賦值重載全都私有化

CState_Runaway(){};

CState_Runaway(const CState_Runaway&);

CState_Runaway& operator=(const CState_Runaway&);

void Run(){cout<<"I will run away!"<<endl;}

public:

void execute(CTroll* troll);

static CState_Runaway* GetInstance(); //靜態實例化函數

};

靜態實例化函數實現如下:

CState_Runaway* CState_Runaway::GetInstance()

{

static CState_Runaway runaway; //local static對象

return &runaway;

}

靜態實例化函數調用:

void CState_Runaway::execute(CTroll* troll)

{

if (troll->GetSafe())

{

troll->ChageState(CState_Sleep::Getinstance());

/*靜態實例化函數第一次調用時local static對象才被執行,實例化成功後,以後再調用就不會執行了。*/

}

else

{

Run();

}

}

最後別忘了把CTroll的析構函數刪除狀態指針的語句去掉。

CTroll::~CTroll(void)

{

//delete m_pCurrentState; //由於是靜態對象,所以不能用delete刪除。delete只能刪除heap里的對象,而靜態對象在全局區里,隨程序結束自動銷毀。

}

用singleton模式後,每種狀態實例只有一個,全局存在,所以以後智能體不管切換多少次狀態都不需要再重新申請內存,大大減少運行時間。

推薦閱讀:

駕馭AI:好的數據集是成功的一半
淺談強人工智慧的瓶頸和可能的努力方向
一位00後由國內外教育經歷所引發的思考
振奮,嗨翻 | AWS re:Invent 2017 第二天回顧
百年奧運是一部科技史,智能奧運在平昌冬奧會浮出水面

TAG:人工智慧 |