专业的编程技术博客社区

网站首页 > 博客文章 正文

C++精品案例-音乐播放器与状态模式

baijin 2024-10-01 07:34:35 博客文章 8 ℃ 0 评论

承接上文,本文用C++语言,用面向对象的思想,结合状态模式来实现音乐播放器。

题目要求

用C语言实现一个音乐播放器的框架

  • 播放器有3个状态:停止状态、播放状态、暂停状态
  • 播放器有3个按键:播放按键、暂停按键、停止按键
  • 播放器启动后进入到停止状态,停止状态下只响应播放按键,按下播放按键进入播放状态,并开始播放音乐;播放状态下,不响应播放按键,按下暂停键暂停音乐播放,按下停止键停止音乐播放;暂停状态下,不响应暂停按键,按下播放键继续播放音乐,按下停止键停止播放音乐。

补充说明:

    • 本案例重点体现设计思想和编程思想
    • 界面不限,可以基于命令行,也可以基于图形界面
    • 不需要真正能播放音乐,通过输出不同的字符串来表示执行了相关动作即可,比如:播放开始打印"Playing"字符串,停止时打印"Stop"字符串


状态模式和音乐播放器

关于状态模式,网上介绍的资料很多,这里不做重复描述,这里直接提取状态模式中的干货做一下阐述。

状态模式中有2个重要概念:上下文(context)和状态(state)。

  • 上下文:用来存储播放器在工作过程中用到的信息,
  • 状态:包含2个层面的内容,状态抽象类(C#或Java中用接口),以及状态子类。

上下文如何设计,状态抽象类如何设计,状态子类如何设计,这3个问题是状态模式的核心,也是很多使用状态模式的软件工程师最困惑最拿捏不好的地方,下面结合音乐播放器案例逐一介绍。

抽象类:其重点是设计成员函数,状态抽象类中的成员函数(C#或Java中称为方法)跟状态图中的触发(Trigger)是一一对应的,这是指导思想,比如:播放器有3个触发:停止、播放、暂停,那么抽象类中需要提供3个对应的纯虚成员函数,类图如下:

状态子类:有几个状态,就对应几个状态子类,比如:播放器有3个状态:停止、播放、暂停,那么就应该对应有3个状态子类,类图如下:

上下文:主要用来存储播放器工作过程中依赖的信息,包含2类信息:状态模式本身依赖的信息,以及播放器工作过程中依赖的信息

  • 状态模式本身依赖的信息:比如播放器中,当前的工作状态,另外,为了避免各个子状态的反复new-delete,需要保存每种状态的一个对象实例
  • 播放器工作过程中依赖的信息:本播放器案例过于简单,没有该信息,考虑地稍微复杂一点,播放器当前正在播放的文件的路径、当前的播放时间播放信息等需要存储在上下文中。

其他补充:每个状态子类代表一种状态,该状态下收到触发时,可能需要执行动作并做状态迁移,因此每个状态子类中需要关联播放器的上下文,播放器上下文需要提供能获取特定状态的成员函数,并提供改变当前状态的成员函数,类图如下:

注意:上下文和状态产生了双向依赖,不可在头文件中相互包含对方,因此在编码时需要用到前置声明,代码片段如下:

// PlayerContext.h
// 前置声明
class IPlayerState;

class PlayerContext
{
// Member functions
public:
    PlayerContext();
    ~PlayerContext();
    void setTargetState(IPlayerState *targetState);
    IPlayerState *getStopState();
    IPlayerState *getPlayState();
    IPlayerState *getPauseState();
    // ......
};

// IPlayerState.h
#include "PlayerContext.h"

class IPlayerState
{
// Member functions
public:
    IPlayerState(PlayerContext *playerContext)
    {
        m_playerContext = playerContext;
    }
    virtual void play() = 0;
    virtual void pause() = 0;
    virtual void stop() = 0;
    // ......
}

C++代码实现

上面给出了设计指导,代码实现部分只给出头文件,如下文:

IPlayerState.h文件

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    IPlayerState.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __IPLAYERSTATE_H__
#define __IPLAYERSTATE_H__

#include "PlayerContext.h"

class IPlayerState
{
// Member functions
public:
    IPlayerState(PlayerContext *playerContext)
    {
        m_playerContext = playerContext;
    }
    virtual void play() = 0;
    virtual void pause() = 0;
    virtual void stop() = 0;
 
// Member Variables
protected:
    PlayerContext *m_playerContext;     // 为了在子类中能访问到,这里定义为protected属性
};

#endif /* __IPLAYERSTATE_H__ */

PlayerContext.h文件

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    PlayerContext.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __PLAYERCONTEXT_H__
#define __PLAYERCONTEXT_H__

// 前置声明
class IPlayerState;

class PlayerContext
{
// Member functions
public:
    PlayerContext();
    ~PlayerContext();
    void setTargetState(IPlayerState *targetState);
    IPlayerState *getStopState();
    IPlayerState *getPlayState();
    IPlayerState *getPauseState();

    void play();
    void pause();
    void stop();  
// Member Variables
private:
    IPlayerState *m_currentState;
    IPlayerState *m_stopState;
    IPlayerState *m_playState;
    IPlayerState *m_pauseState;
};

#endif /* __PLAYERCONTEXT_H__ */

PlayerStateStop.h文件

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    PlayerStateStop.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __PLAYERSTATESTOP_H__
#define __PLAYERSTATESTOP_H__

#include "IPlayerState.h"

class PlayerStateStop: public IPlayerState
{
// Member functions
public:
    PlayerStateStop(PlayerContext *playerContext);
    virtual void play();
    virtual void pause();
    virtual void stop();
};

#endif /* __PLAYERSTATESTOP_H__ */

PlayerStatePlay.h文件

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    PlayerStatePlay.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __PLAYERSTATEPLAY_H__
#define __PLAYERSTATEPLAY_H__

#include "IPlayerState.h"

class PlayerStatePlay: public IPlayerState
{
// Member functions
public:
    PlayerStatePlay(PlayerContext *playerContext);
    virtual void play();
    virtual void pause();
    virtual void stop();
};

#endif /* __PLAYERSTATEPLAY_H__ */

PlayerStatePause.h文件

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    PlayerStatePause.h
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/
#ifndef __PLAYERSTATEPAUSE_H__
#define __PLAYERSTATEPAUSE_H__

#include "IPlayerState.h"

class PlayerStatePause: public IPlayerState
{
// Member functions
public:
    PlayerStatePause(PlayerContext *playerContext);
    virtual void play();
    virtual void pause();
    virtual void stop();
};

#endif /* __PLAYERSTATEPAUSE_H__ */

测试代码:

/******************************************************************************
 *  Copyright 2022
 *
 *  @file    main.cpp
 *
 *  @brief   
 *
 *=============================================================================
 *  Revision History
 *  Version     Date        Author      Content
 *  -------     ----------  ---------   ---------------------------------------
 *  V1.00       2022/12/10  yangyf      Create.
 *
 *****************************************************************************/

/******************************************************************************
 *
 * INCLUDES
 *
 *****************************************************************************/
#include "plat.h"
#include "PlayerContext.h"

/******************************************************************************
 *
 * FUNCTIONS
 *
 *****************************************************************************/
int main()
{
    plat_init();
    PlayerContext playerContext;
    int input;
    while(1) {
        log_print("Press key:\n");
        log_print(" 0, Stop key\n");
        log_print(" 1, Play key\n");
        log_print(" 2, Pause key\n");
        scanf("%d", &input);
        getchar();
        switch(input) {
            case 0:
            playerContext.stop();
            break;
            case 1:
            playerContext.play();
            break;
            case 2:
            playerContext.pause();
            break;
        }
    }

    return 0;
}
/* - End Of File - */

~ END ~

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表