利用工厂模式实现怪物系统
生活随笔
收集整理的這篇文章主要介紹了
利用工厂模式实现怪物系统
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
利用工廠模式可以有效的降低類與類的藕合性,增強代碼的可重用性,工廠模式主要通過虛函數的原理進行。
當基類指針指向一個子類對象,通過這個指針調用子類和基類同名成員函數的時候,基類聲明為虛函數「子類不寫也可以」就會調子類的這個函數,不聲明就會調用基類的。
虛析構函數的作用
我們知道,用C++開發的時候,用來做基類的類的析構函數一般都是虛函數。可是,為什么要這樣做呢?下面用一個小例子來說明: 有下面的兩個類:class ClxBase { public:ClxBase() {};virtual ~ClxBase() {};virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; }; };class ClxDerived : public ClxBase { public:ClxDerived() {};~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; void DoSomething() { cout << "Do something in class ClxDerived!" << endl; }; };代碼ClxBase *pTest = new ClxDerived; pTest->DoSomething(); delete pTest;的輸出結果是:Do something in class ClxDerived! Output from the destructor of class ClxDerived!這個很簡單,非常好理解。但是,如果把類ClxBase析構函數前的virtual去掉,那輸出結果就是下面的樣子了:Do something in class ClxDerived!也就是說,類ClxDerived的析構函數根本沒有被調用!一般情況下類的析構函數里面都是釋放內存資源,而析構函數不被調用的話就會造成內存泄漏。我想所有的C++程序員都知道這樣的危險性。當然,如果在析構函數中做了其他工作的話,那你的所有努力也都是白費力氣。所以,文章開頭的那個問題的答案就是--這樣做是為了當用一個基類的指針刪除一個派生類的對象時,派生類的析構函數會被調用。當然,并不是要把所有類的析構函數都寫成虛函數。因為當類里面有虛函數的時候,編譯器會給類添加一個虛函數表,里面來存放虛函數指針,這樣就會增加類的存儲空間。所以,只有當一個類被用來作為基類的時候,才把析構函數寫成虛函數工廠模式實現
工廠類
#ifndef __Item_H__ #define __Item_H__#include "Common.h" class Mario;// 基類,和工廠類 // 分割模塊(讓模塊之間搞內聚,低耦合) // 多態(虛函數) class Item : public CCSprite { public:enum ItemType{IT_mushroom, IT_tortoise, IT_flower, IT_mushroomReward, IT_mushroomAddLife, IT_flagpoint};// Item* item; delete item;virtual ~Item();// 所有道具都需要調用的初始化工作bool init(){CCSprite::init();setZOrder(100);// 為道具提供動力scheduleUpdate();return true;}Mario* _mario;static CCArray* _itemReward;static Item* _Flag;// 工廠接口static Item* create(CCDictionary* dict);// 對象的虛接口virtual void move(float dt) {}virtual void collision() {}virtual void wakeup(){}void update(float dt){move(dt);collision();}////////////////////////////// 公共輔助函數void setPositionByProperty(CCDictionary* dict){const CCString* x = dict->valueForKey("x");const CCString* y = dict->valueForKey("y");setPosition(ccp(x->intValue(), y->intValue() - 16));setAnchorPoint(ccp(0, 0));}CCTMXTiledMap* getMap(){return (CCTMXTiledMap*)getParent();}bool isLeftInWindow(){// CCPoint ptInMap = getPosition();CCRect rcItem = boundingBox();CCPoint ptInMap = ccp(rcItem.getMinX(), rcItem.getMinY());CCTMXTiledMap* map = getMap();CCPoint ptInWorld = map->convertToWorldSpace(ptInMap);if (ptInWorld.x <= winSize.width){return true;}return false;}bool isFarAwayFromMario();ItemType _type; };#if 0 class ItemFactroy { public:Item* createItem(Item::ItemType it){return Item::create(it);} }; #endif#endif工廠接口實現
#include "Item.h" #include "ItemMushroom.h" #include "Mario.h" #include "ItemTortoise.h" Item::~Item() {} Item* Item::create(CCDictionary* dict) {const CCString *type=dict->valueForKey("type");if (type->m_sString=="mushroom"){return ItemMushroom::create(dict);}else if (type->m_sString == "tortoise")return ItemTortoise::create(dict);return NULL;}bool Item::isOutOfWindow() {CCRect rcItem=this->boundingBox();CCRect rcMario=_mario->boundingBox();if (rcMario.getMinX()-rcItem.getMaxX()>winSize.width){return true;}return false; }使用工廠模式,就不用在游戲中加入各個怪物的頭文件,只需要包含Item.h就可以了,降低了怪物層與游戲層的藕合性,增強了內聚性,同時也增強了代碼的重用性。
總結
以上是生活随笔為你收集整理的利用工厂模式实现怪物系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7.Mysql数据库表引擎与字符集
- 下一篇: Android之自定义属性