C++定时器的实现与应用

论坛 期权论坛 脚本     
匿名技术用户   2020-12-27 00:31   113   0

主要目标

(暂时还有一些格式、规范的问题,可运行)


每过5秒钟,从鸭笼里随机放出一只鸭子,鸭子出笼后,很开心的发出了自己的叫声。自从这只鸭子放出后7秒后,鸭子觉得无趣,回到笼子去休息了。每过13秒,鸭笼里就会生下一只全新的鸭子(种类随机)。

主要思路


HTimeOut是一个抽象观察者,时间管理器(TimerServer)是主题,鸭子(Duck)鸭笼(DuckCage)这些用到定时器(Timer)的东西去继承观察者,然后再时间管理器中注册,等时间到了就时间管理器就向订阅了相应主题的观察者发通知,就是调用他们的回调函数HTimeOut中有一个OnTimeOut函数作为回调用。

定时器类

//Timer.h
class CTimer
{
public:
    bool IsRing(int nTimeNow);//响应函数
    bool IsLoop();//是否循环使用
    bool TimerUpdate(int nTimeStart);//更新起始时间Sec
    HTimeOut* GetHTimeOut();
    CTimer(HTimeOut* pTimeOut,int nInterval, int nTimeStart, bool bLoop);
    virtual ~CTimer(){};
private:
    HTimeOut* _pTimeOut;//抽象观察者
    int _nInterval;//定时时间Sec
    int _nTimeStart;//开始时间Sec
    bool _bLoop;
};
//Timer.cpp
bool CTimer::IsRing(int nTimeNow)
{
        if(_nInterval <= nTimeNow-_nTimeStart)
            return true;
        else
            return false;
}
bool CTimer::IsLoop()
{
    return _bLoop;
}
bool CTimer::TimerUpdate(int nTimeStart)
{
    this->_nTimeStart = nTimeStart;
    return true;
}
HTimeOut* CTimer::GetHTimeOut()
{
    return _pTimeOut;
}
CTimer::CTimer(HTimeOut* pTimeOut, int nInterval, int nTimeStart, bool bLoop)
{
    this->_pTimeOut = pTimeOut;
    this->_nInterval = nInterval;
    this->_nTimeStart = nTimeStart;
    this->_bLoop = bLoop;
}

定时器管理器类

//TimerServer.h
class CTimerServer
{
public:
    CTimer* TimerCreate(HTimeOut* pTimeOut,int nInterval, int nTimeStart, bool bLoop);//创建一个定时器
    bool TimerDestory(CTimer* pTimer);//销毁定时器
    bool TimerScanning(int ntTimeNow);//每一个时间片来扫描所有定时器,超时就回调OnTimeOut
    CTimerServer(){};
    virtual ~CTimerServer(){};
    static int _TimeSec;//静态变量表示时间Sec
private:
     std::vector<CTimer* > _vTimer;//定时器容器
};

//TimerServer.cpp
int CTimerServer::_TimeSec = 0;//静态变量初始化
CTimer* CTimerServer::TimerCreate(HTimeOut* pTimeOut,int nInterval, int nTimeStart, bool bLoop)
{
    CTimer* cTimer = new CTimer(pTimeOut, nInterval, nTimeStart, bLoop);
    _vTimer.push_back(cTimer);
    return cTimer;
}
bool CTimerServer::TimerDestory(CTimer* pTimer)
{
    delete pTimer;
    return true;
}
bool CTimerServer::TimerScanning(int nTimeNow )
{
    std::vector<CTimer* > vTimerCopy(_vTimer);//在for循环中因为有回调可能产生新的定时器而改变vector,直接循环会出错误,所以复制一份用于for循环扫描
    _vTimer.clear();
    for (std::vector<CTimer* >::iterator itrIteratorCopy = vTimerCopy.begin(); itrIteratorCopy != vTimerCopy.end(); )
    {
        if ((*itrIteratorCopy)->IsRing(nTimeNow))
        {
            //回调
            (*itrIteratorCopy)->GetHTimeOut()->OnTimeOut(*itrIteratorCopy);

            if (!(*itrIteratorCopy)->IsLoop())
            {
                TimerDestory(*itrIteratorCopy);
                itrIteratorCopy = vTimerCopy.erase(itrIteratorCopy);
            }
            else
            {
                (*itrIteratorCopy)->TimerUpdate(nTimeNow);
                ++itrIteratorCopy;
            }
        }
        else
        {
            ++itrIteratorCopy;
        }
    }
    std::vector<CTimer* >::iterator itrIterator = _vTimer.begin();
    for(;itrIterator!=_vTimer.end();++itrIterator)
    {
        vTimerCopy.push_back(*itrIterator);
    }
    _vTimer.swap(vTimerCopy);
    return true;
}

抽象观察者类

//TimeOut.h
class HTimeOut
{
public:
    virtual bool OnTimeOut(CTimer* pTimer)=0;//纯虚函数,留给子类实现具体逻辑
    HTimeOut() {};
    virtual ~HTimeOut() {};
};

抽象鸭子类和鸭子类和工厂类

//AbstractDuck.h
class IAbstractDuck:
    public HTimeOut
{
public:
     virtual bool DuckCry();//发出叫声
     virtual bool EnterCage();//进笼子
     virtual bool LeaveCage(CTimer* pTimer);//鸭子出笼子
     virtual bool IsInCage();//是否在笼子
     virtual CTimer* GetTimer();//获得绑定的定时器,通过指针判断
     virtual std::string GetDuckType();//鸭子类别
public:
    virtual bool OnTimeOut(CTimer* pTimer);//回调函数,继承于抽象观察者类
public:
    IAbstractDuck(){};
    virtual ~IAbstractDuck(){};
public:
    CTimer* _pTimeIn;
    std::string _sDuckType;
    std::string _sDuckCry;
    bool _bInCage;
};

//AbstractDuck.cpp
bool IAbstractDuck::DuckCry()
{
    std::cout << _sDuckCry << std::endl;
    return true;
}
bool IAbstractDuck::EnterCage()
{
    std::cout << _sDuckType << "鸭子进笼了。 " << std::endl;
    this->_bInCage = true;
    return true;
}
bool IAbstractDuck::LeaveCage(CTimer* pTimer)
{
    this->_pTimeIn = pTimer;
    std::cout << _sDuckType << "鸭子出笼了。 " << std::endl;
    this->_bInCage = false;
    return true;
}
bool IAbstractDuck::IsInCage()
{
    if (this->_bInCage)
        return true;
    else
        return false;
}
CTimer* IAbstractDuck::GetTimer()
{
    return _pTimeIn;
}
std::string IAbstractDuck::GetDuckType()
{
    return _sDuckType;
}
bool IAbstractDuck::OnTimeOut(CTimer* pTimer)
{
    this->EnterCage();
    return true;
}

//Duck.h 鸭子类:6种鸭子
class CDuckGold :
    public IAbstractDuck
{
public:
    CDuckGold();
    virtual ~CDuckGold(){};
};
class CDuckPlastic :
    public IAbstractDuck
{
public:
    CDuckPlastic();
    virtual ~CDuckPlastic(){};
};
class CDuckRubber :
    public IAbstractDuck
{
public:
    CDuckRubber();
    virtual ~CDuckRubber(){};
};
class CDuckSilver :
    public IAbstractDuck
{
public:
    CDuckSilver();
    virtual ~CDuckSilver(){};
};
class CDuckTin :
    public IAbstractDuck
{
public:
    CDuckTin();
    virtual ~CDuckTin(){};
};
class CDuckWood :
    public IAbstractDuck
{
public:
    CDuckWood();
    virtual ~CDuckWood(){};
};

//Duck.cpp
CDuckGold::CDuckGold()
{
    _sDuckType = "金";
    _sDuckCry = "金金金";
    _pTimeIn = nullptr;
    _bInCage = true;
}
CDuckPlastic::CDuckPlastic()
{
    _sDuckType = "塑料";
    _sDuckCry = "塑料塑料塑料";
    _pTimeIn = nullptr;
    _bInCage = true;
}
CDuckRubber::CDuckRubber()
{
    _sDuckType = "橡皮";
    _sDuckCry = "橡皮橡皮橡皮";
    _pTimeIn = nullptr;
    _bInCage = true;
}
CDuckSilver::CDuckSilver()
{
    _sDuckType = "银";
    _sDuckCry = "银银银";
    _pTimeIn = nullptr;
    _bInCage = true;
}
CDuckTin::CDuckTin()
{
    _sDuckType = "锡";
    _sDuckCry = "锡锡锡";
    _pTimeIn = nullptr;
    _bInCage = true;
}
CDuckWood::CDuckWood()
{
    _sDuckType = "木头";
    _sDuckCry = "木头木头木头";
    _pTimeIn = nullptr;
    _bInCage = true;
}

//DuckFactory.h 简单工厂模式
class CDuckFactory
{
public:
    IAbstractDuck * CreateDuck(EDuckType eDuckType);//产生并返回一只随机的新鸭子
    bool DestoryDuck(IAbstractDuck* pAbstractDuck);//销毁传入的鸭子delelte
    CDuckFactory(){};
    virtual ~CDuckFactory(){};
};

//DuckFactory.cpp
IAbstractDuck* CDuckFactory::CreateDuck(EDuckType eDuckType)//枚举类型
{
    switch (eDuckType)
    {
    case DUCK_TYPE_GOLD:     return new CDuckGold(); break;
    case DUCK_TYPE_PLASTIC:  return new CDuckPlastic(); break;
    case DUCK_TYPE_RUBBER:   return new CDuckRubber(); break;
    case DUCK_TYPE_SILVER:   return new CDuckSilver(); break;
    case DUCK_TYPE_TIN:      return new CDuckTin(); break;
    case DUCK_TYPE_WOOD:     return new CDuckWood(); break;
    default:                 return nullptr; break;
    }
}

bool CDuckFactory::DestoryDuck(IAbstractDuck* pAbstractDuck)
{
    delete pAbstractDuck;
    return true;
}

鸭笼类

//DuckCage.h
class CDuckCage : public HTimeOut
{
public:
    bool ShowDuckState();//显示鸭子的状态(是否在笼子里)
    bool SetTimer(CTimer* pDuckOut, CTimer* pDuckNew);//设置定时器
    bool AddDuck(IAbstractDuck* pAbstractDuck);//往笼子中添加鸭子
    bool RemoveDuck();//删除笼子里所有鸭子
    IAbstractDuck* GetDuck(CTimer* pTimer);//通过定时器的地址来返回匹配的鸭子
public:
    virtual bool OnTimeOut(CTimer* pTimer);//回调函数,继承于抽象观察者类
public:
    CDuckCage(){};
    CDuckCage(CTimer* pDuckOut, CTimer* pDuckNew, CTimerServer* pTimerServer, CDuckFactory* pDuckFactory);
    virtual ~CDuckCage(){};
private:
    CTimer* _pTimeOut;
    CTimer* _pTimeNew;
    CTimerServer* _pTimerServer;//定时器管理器
    CDuckFactory* _pDuckFactory;//工厂模式,建鸭子的工厂
    std::vector<IAbstractDuck* > _vDuckCage;//鸭子容器
};

//DuckCage.cpp
bool CDuckCage::ShowDuckState()
{
    int nDuckInCage = 0;
    int nDuckOutCage = 0;
    for (std::vector<IAbstractDuck* >::iterator itrIterator = _vDuckCage.begin(); itrIterator != _vDuckCage.end(); ++itrIterator)
    {
        if ((*itrIterator)->IsInCage())
            nDuckInCage++;
        else
            nDuckOutCage++;
    }
    std::cout << "在笼子中:" << nDuckInCage << "  不在笼子中:" << nDuckOutCage << std::endl;
    return true;
}
bool CDuckCage::SetTimer(CTimer* pDuckOut, CTimer* pDuckNew)
{
    this->_pTimeNew = pDuckNew;
    this->_pTimeOut = pDuckOut;
    return true;
}
bool CDuckCage::AddDuck(IAbstractDuck* pAbstractDuck)
{
    _vDuckCage.push_back(pAbstractDuck);
    return true;
}
bool CDuckCage::RemoveDuck()
{
    for (std::vector<IAbstractDuck* >::iterator itrIterator = _vDuckCage.begin(); itrIterator != _vDuckCage.end(); ++itrIterator)
    {
        _pDuckFactory->DestoryDuck(*itrIterator);
    }
    _vDuckCage.clear();
    return true;
}
IAbstractDuck* CDuckCage::GetDuck(CTimer* pTimer)
{
    for (std::vector<IAbstractDuck* >::iterator itrIterator = _vDuckCage.begin(); itrIterator != _vDuckCage.end(); ++itrIterator)
        {
        if ((*itrIterator)->GetTimer() == pTimer)
            return *itrIterator;
        }
    return  nullptr;
}
bool CDuckCage::OnTimeOut(CTimer* pTimer)//重载
{
    if (this->_pTimeNew==pTimer)//通过定时器的地址匹配
    {
        int eNumberInit = DUCK_INIT_COUNT;//枚举类型12
        ENumber eRandMMin = RAND_MMIN;//枚举类型1
        ENumber eDuckTypeCount = DUCK_TYPE_COUNT;//枚举类型6
        srand((int)time(NULL));
        EDuckType eDuckType = EDuckType((rand() % eDuckTypeCount + eRandMMin));//随机产生鸭子类型

        this->_vDuckCage.push_back(_pDuckFactory->CreateDuck(eDuckType));
        if (eNumberInit <= (int)_vDuckCage.size())
            std::cout << "一只新鸭子进笼了。" << std::endl;

        pTimer->TimerUpdate(CTimerServer::_TimeSec);

    }
    else if (this->_pTimeOut == pTimer)
    {
        ENumber eRandMin = RAND_MMIN;//1
        ETimerCallBack eTimerCallBack = CALL_BACK_IN;//7
        srand((int)time(NULL));
        int nState = rand() % _vDuckCage.size() + eRandMin;
        std::vector<IAbstractDuck* >::iterator itrIterator = _vDuckCage.begin() + --nState;
        if (!(*itrIterator)->IsInCage())
        {
            while (!(*itrIterator)->IsInCage())
            {
                nState = rand() % _vDuckCage.size() + eRandMin;
                itrIterator = _vDuckCage.begin() + --nState;
            }
        }
        (*itrIterator)->LeaveCage(this->_pTimerServer->TimerCreate(*itrIterator, eTimerCallBack, CTimerServer::_TimeSec, false));
        (*itrIterator)->DuckCry();
        pTimer->TimerUpdate(CTimerServer::_TimeSec);
    }
    return true;
}
CDuckCage::CDuckCage(CTimer* pDuckOut, CTimer* pDuckNew, CTimerServer* pTimerServer,                         CDuckFactory* pDuckFactory)
{
    if (pDuckOut != nullptr)
    {
        this->_pTimeOut = pDuckOut;
    }
    else
        this->_pTimeOut = nullptr;
    if (pDuckNew != nullptr)
    {
        this->_pTimeNew = pDuckNew;
    }
    else
        this->_pTimeNew = nullptr;
    this->_pTimerServer = pTimerServer;
    this->_pDuckFactory = pDuckFactory;
}

总结


这里写图片描述


每一个时间片定时器管理器都会扫描所有定时器,所有超时的定时器会利用创建定时器是传入的HTimeOut指针进行OnTimeOut()回调,OnTimeOut()函数在抽象类中是个纯虚函数,在子类重载,从而回到上层逻辑,实现定时器的作用。

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP