1. 历时两天,完整且完美的设计了宠物类,使用到了多种设计模式,完成了低耦合,高内聚的完美代码,测试也完美通过。
2. 顺便完善了底层通信类的封装,基于websocket,基准测试通过,但存在一点很小的线程bug,似乎是来自于esp32 idf底层的问题,待解决
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
//
|
||||
// Created by misaki on 2025/9/14.
|
||||
//
|
||||
#pragma once
|
||||
#include "PetInterface.h"
|
||||
// 宠物音频播放观察者类,继承自宠物观察者
|
||||
class PetAudioStrategy : public PetObserver, public std::enable_shared_from_this<PetAudioStrategy> {
|
||||
public:
|
||||
using AudioCallback = std::function<void(const std::string&)>;
|
||||
/**
|
||||
* 构造时候就将“事件→音频”两张表填好
|
||||
* @param actionAudios 动作→音频
|
||||
* @param stageAudios 阶段→音频
|
||||
*/
|
||||
explicit PetAudioStrategy(
|
||||
std::unordered_map<PetActionType, std::string> actionAudios = {},
|
||||
std::unordered_map<PetStageType, std::string> stageAudios = {})
|
||||
: action_audio(std::move(actionAudios)),
|
||||
stage_audio(std::move(stageAudios))
|
||||
{}
|
||||
/**
|
||||
* 构造函数,需要传入阶段策略和动作策略,从其中获取所需的类型→模型路径映射
|
||||
* @param stageStrategy 阶段策略
|
||||
* @param actionStrategy 动作策略
|
||||
*/
|
||||
explicit PetAudioStrategy(
|
||||
const std::shared_ptr<PetStageStrategy>& stageStrategy,
|
||||
const std::shared_ptr<PetActionStrategy>& actionStrategy) {
|
||||
stage_audio = stageStrategy->getStageAudioMap(); // 获取阶段→音频map
|
||||
action_audio = actionStrategy->getActionAudioMap(); // 获取动作→音频map
|
||||
}
|
||||
|
||||
~PetAudioStrategy() override {
|
||||
// 自动取消注册
|
||||
if (auto subject = pet_subject.lock()) {
|
||||
subject->removeObserver(shared_from_this());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置音频播放回调函数,注入真正的“播放函数”,由外部(主程序 / 平台层)提供
|
||||
* @param callback 音频播放回调,接受音频文件路径
|
||||
*/
|
||||
virtual void setAudioCallback(AudioCallback callback) {
|
||||
audio_callback = std::move(callback);
|
||||
}
|
||||
/**
|
||||
* 注册到 Subject(一般由 Pet 基类实现)
|
||||
* @param subject 主题
|
||||
*/
|
||||
void subscribe(std::shared_ptr<PetSubject> subject)
|
||||
{
|
||||
if (auto old = pet_subject.lock()) {
|
||||
old->removeObserver(shared_from_this());
|
||||
}
|
||||
pet_subject = subject;
|
||||
if (subject) {
|
||||
subject->addObserver(shared_from_this());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 宠物动作时触发[Observer 接口实现]
|
||||
* @param action 动作
|
||||
*/
|
||||
void onPetAction(const PetActionType action) override
|
||||
{
|
||||
if (!audio_callback) return;
|
||||
auto it = action_audio.find(action);
|
||||
if (it != action_audio.end()) {
|
||||
audio_callback(it->second); // 播放对应音频
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 宠物阶段时触发[Observer 接口实现]
|
||||
* @param oldStage 旧阶段
|
||||
* @param newStage 新阶段
|
||||
*/
|
||||
void onPetStageChange(PetStageType oldStage, const PetStageType newStage) override
|
||||
{
|
||||
if (!audio_callback) return;
|
||||
auto it = stage_audio.find(newStage); // 注意:播“新阶段”的音频
|
||||
if (it != stage_audio.end()) {
|
||||
audio_callback(it->second);
|
||||
}
|
||||
}
|
||||
private:
|
||||
///<! 宠物音频播放回调
|
||||
AudioCallback audio_callback;
|
||||
///<! 宠物主题
|
||||
std::weak_ptr<PetSubject> pet_subject;
|
||||
///<! 两张映射表,保证“同一事件只对应一种音频”
|
||||
std::unordered_map<PetActionType, std::string> action_audio;
|
||||
std::unordered_map<PetStageType, std::string> stage_audio;
|
||||
};
|
||||
|
||||
// 渲染器观察者类,继承自PetObserver
|
||||
class PetRendererStrategy : public PetObserver, public std::enable_shared_from_this<PetRendererStrategy> {
|
||||
public:
|
||||
using RenderCallback = std::function<void(const std::string&)>;
|
||||
/**
|
||||
* 构造函数,可以传入动作到模型路径和阶段到模型路径的映射表
|
||||
* @param actionModels 动作→模型路径映射
|
||||
* @param stageModels 阶段→模型路径映射
|
||||
*/
|
||||
explicit PetRendererStrategy(
|
||||
std::unordered_map<PetActionType, std::string> actionModels = {},
|
||||
std::unordered_map<PetStageType, std::string> stageModels = {})
|
||||
: action_models(std::move(actionModels)),
|
||||
stage_models(std::move(stageModels))
|
||||
{}
|
||||
/**
|
||||
* 构造函数,需要传入阶段策略和动作策略,从其中获取所需的类型→模型路径映射
|
||||
* @param stageStrategy 阶段策略
|
||||
* @param actionStrategy 动作策略
|
||||
*/
|
||||
explicit PetRendererStrategy(
|
||||
const std::shared_ptr<PetStageStrategy>& stageStrategy,
|
||||
const std::shared_ptr<PetActionStrategy>& actionStrategy) {
|
||||
stage_models = stageStrategy->getStageModelMap();
|
||||
action_models = actionStrategy->getActionModelMap();
|
||||
}
|
||||
~PetRendererStrategy() override {
|
||||
// 自动取消注册
|
||||
if (auto subject = pet_subject.lock()) {
|
||||
subject->removeObserver(shared_from_this());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 设置渲染回调函数,注入真正的"渲染函数",由外部(主程序/平台层)提供
|
||||
* @param callback 渲染回调,接受模型文件路径
|
||||
*/
|
||||
virtual void setRenderCallback(RenderCallback callback) {
|
||||
render_callback = std::move(callback);
|
||||
}
|
||||
/**
|
||||
* 注册到Subject(一般由Pet基类实现)
|
||||
* @param subject 主题
|
||||
*/
|
||||
void subscribe(std::shared_ptr<PetSubject> subject) {
|
||||
if (auto old = pet_subject.lock()) {
|
||||
old->removeObserver(shared_from_this());
|
||||
}
|
||||
pet_subject = subject;
|
||||
if (subject) {
|
||||
subject->addObserver(shared_from_this());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 宠物动作时触发[Observer接口实现]
|
||||
* @param action 动作类型
|
||||
*/
|
||||
void onPetAction(PetActionType action) override {
|
||||
if (!render_callback) return;
|
||||
auto it = action_models.find(action);
|
||||
if (it != action_models.end()) {
|
||||
render_callback(it->second); // 渲染对应动作模型
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 宠物阶段变化时触发[Observer接口实现]
|
||||
* @param oldStage 旧阶段
|
||||
* @param newStage 新阶段
|
||||
*/
|
||||
void onPetStageChange(PetStageType oldStage, PetStageType newStage) override {
|
||||
if (!render_callback) return;
|
||||
auto it = stage_models.find(newStage); // 注意:渲染"新阶段"的模型
|
||||
if (it != stage_models.end()) {
|
||||
render_callback(it->second);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 添加动作到模型的映射
|
||||
* @param action 动作类型
|
||||
* @param modelPath 模型路径
|
||||
*/
|
||||
virtual void addActionModel(PetActionType action, const std::string& modelPath) {
|
||||
action_models[action] = modelPath;
|
||||
}
|
||||
/**
|
||||
* 添加阶段到模型的映射
|
||||
* @param stage 阶段类型
|
||||
* @param modelPath 模型路径
|
||||
*/
|
||||
virtual void addStageModel(PetStageType stage, const std::string& modelPath) {
|
||||
stage_models[stage] = modelPath;
|
||||
}
|
||||
/**
|
||||
* 移除动作模型映射
|
||||
* @param action 动作类型
|
||||
*/
|
||||
virtual void removeActionModel(PetActionType action) {
|
||||
action_models.erase(action);
|
||||
}
|
||||
/**
|
||||
* 移除阶段模型映射
|
||||
* @param stage 阶段类型
|
||||
*/
|
||||
virtual void removeStageModel(PetStageType stage) {
|
||||
stage_models.erase(stage);
|
||||
}
|
||||
private:
|
||||
///<! 渲染回调函数
|
||||
RenderCallback render_callback;
|
||||
///<! 宠物主题
|
||||
std::weak_ptr<PetSubject> pet_subject;
|
||||
///<! 动作到模型路径的映射表
|
||||
std::unordered_map<PetActionType, std::string> action_models;
|
||||
///<! 阶段到模型路径的映射表
|
||||
std::unordered_map<PetStageType, std::string> stage_models;
|
||||
};
|
||||
Reference in New Issue
Block a user