• 利用工厂模式实现怪物系统


    利用工厂模式可以有效的降低类与类的藕合性,增强代码的可重用性,工厂模式主要通过虚函数的原理进行。

    当基类指针指向一个子类对象,通过这个指针调用子类和基类同名成员函数的时候,基类声明为虚函数「子类不写也可以」就会调子类的这个函数,不声明就会调用基类的。

    虚析构函数的作用

     我们知道,用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就可以了,降低了怪物层与游戏层的藕合性,增强了内聚性,同时也增强了代码的重用性。

  • 相关阅读:
    BZOJ 3158: 千钧一发
    BZOJ 1677: [Usaco2005 Jan]Sumsets 求和
    BZOJ 1574: [Usaco2009 Jan]地震损坏Damage
    BZOJ 1644: [Usaco2007 Oct]Obstacle Course 障碍训练课
    BZOJ 1715: [Usaco2006 Dec]Wormholes 虫洞
    BZOJ 1634: [Usaco2007 Jan]Protecting the Flowers 护花
    Vijos P1740聪明的质检员
    Vijos P1680距离
    Vijos P1067Warcraft III 守望者的烦恼
    BZOJ 1385: [Baltic2000]Division expression
  • 原文地址:https://www.cnblogs.com/jjx2013/p/6223747.html
Copyright © 2020-2023  润新知