《游戏编程模式》各种模式汇总(一)

出于对自己的屎山代码的难以忍受,终于在2023.2开始了《游戏编程模式》的学习,总结了一些书里面提到的模式。有些很少用就暂时没去总结。本书共有19种模式,部分模式是游戏编程常用而其他行业软件开发不怎么用的。

  1. 单例模式

优缺点:

1)某些管理类需要满足,全局只有一个实例,如文件读入读出系统,如果有两个实例,

会导致,同时对同一个文件进行写入,造成冲突

2)这些管理类,按照传统的设计模式,应该提供全局访问点。

3)当希望保证只有一个实例,无需提供全局访问点的方式:

/*---------------------------------单例模式-----------------------------
*/

// -------------------------------Demo-----------------------------//
// 准确的说,这是一个静态类
class FileSystem
{
private:
    FileSystem();
    static FileSystem _instance;

public:
    static FileSystem &instance() { return _instance; }

    // 这个才是真正意义的单例
    /*
    static FileSystem &instance()
    {
        FileSystem *instance = new FileSystem();
        return *instance;
    }
     */
};
  1. 服务定位器

更加灵活、更加可配置的单例模式扩展。

/*---------------------------------服务定位器模式-----------------------------
*/

// -------------------------------Demo-----------------------------//
// 服务
class Audio
{
public:
    virtual void playSound(int ID) = 0;
    virtual void stopSound(int ID) = 0;
    virtual ~Audio() {}
};

// 实现类
class ConsoleAudio : public Audio
{
public:
    virtual void playSound(int ID) override
    {
        // 实现播放声音
    }
    virtual void stopSound(int ID) override
    {
        // 实现停止播放
    }
};

// 服务定位器
class Locator
{
private:
    static Audio *_service;
    static NullAudio _nullAudio;

public:
    static void initialize() { _service = &_nullAudio; }
    // 暴露的服务接口,调用者只需要调用getAudio()就可以获得服务,无需知道谁提供了服务
    static Audio &getAudio() { return *_service; }
    // 依赖注入,外部代码负责注入定位器需要的服务
    static void provide(Audio *service)
    {
        if (service == nullptr)
            initialize();
        else
            _service = service;
    }
};

// 为了保证Locator::getAudio()返回的不是一个空指针,使用一个空对象
class NullAudio : public Audio
{
public:
    virtual void playSound(int ID) override
    { /* 什么也不做 */
    }
    virtual void stopSound(int ID) override
    { /* 什么也不做 */
    }
};

// main function
int main(int argc, char const *argv[])
{
    // 创建真正提供播放声音服务的类对象
    ConsoleAudio *audio = new ConsoleAudio();
    // 注入定位器
    Locator::provide(audio);
    // 获得服务
    Locator::getAudio().playSound(0);
    return 0;
}

扩展:装饰器模式

可以用来实现日志

/* -------------------------------装饰器模式------------------------------
*/
// -------------------------------Demo----------------------------------
class LoggedAudio : public Audio
{
private:
    void log(const char *message)
    {
        // 记录日志的代码
    }
    // 被装饰的对象
    Audio &_wrapped;

public:
    void enableAudioLogging()
    {
        // 装饰现有的服务
        Audio *service = new LoggedAudio(Locator::getAudio());
        // 注入新服务
        Locator::provide(service);
    }
    LoggedAudio(Audio &wrapped) : _wrapped(wrapped) {}
    // 转发相应的命令
    virtual void playSound(int ID) override
    {
        log("Play sound");
        _wrapped.playSound(ID);
    }
    virtual void stopSound(int ID) override
    {
        log("Stop sound");
        _wrapped.stopSound(ID);
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值