重构 MVC:让经典架构完美适配复杂智能系统的后端业务逻辑层(内附框架示例代码)

发布于:2025-07-26 ⋅ 阅读:(11) ⋅ 点赞:(0)

🔥挖到宝!这个 AI 学习网站简直神仙级存在!

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。前言 – 人工智能教程


软件开发—重构MVC


目录

软件开发—重构MVC

一、传统MVC架构

二、改进MVC架构

1.核心改进思路:拆分Model层,明确职责边界

2.关键改进点:让复杂业务逻辑“有处安放”

3.改进后架构对业务逻辑复杂平台的适配性


一、传统MVC架构

        传统的MVC是一种简单直观的架构模式,适合简单的系统应用。例如下面所展示的开源学习项目(https://gitee.com/keanu_zhang/load-balancing-oj-system)“负载均衡OJ系统”早期就是采用经典的MVC架构模式。

简单的”负载均衡OJ系统“

        但纯MVC架构的核心问题是Model层职责过重,因为它既存储数据又包含业务逻辑及模型服务,在业务复杂的系统(蒙古语综合智能平台)中容易导致代码逻辑交织,难以维护扩展。

二、改进MVC架构

        针对这一问题,可通过“分层拆分 Model 层 + 引入领域逻辑封装 + 强化服务协作”进行改进,使其适配复杂业务的系统平台。

1.核心改进思路:拆分Model层,明确职责边界

        将传统MVC的“Model”拆分为数据层、领域层、应用层,让每一层专注单一职责,避免业务逻辑与数据处理混杂。改进分层后,以蒙古语综合智能平台为例,其软件平台后端架构图如下。

蒙古语综合智能平台服务端架构图

其系统服务端下包括文件夹MCIPserver_bll(服务端-业务逻辑层)和MCIPserver_mms(服务端-多模型服务)。

首先:在文件夹MCIPserver_bll(服务端-业务逻辑层)下包括文件BLL.cpp、BLL_view.hpp(视图)、BLL_model.hpp(模型)及BLL_controller.hpp(控制器);还包括文件夹MODEL_tl(模型-三层)。

(1)MCIPserver_bll文件夹->BLL.cpp文件

#include<iostream>
//按开发需求进行头文件的补充...

#include"../MCIP_tool/httplib.h"
#include"./BLL_controller.hpp"

using namespace httplib;
using namespace BLL_controller;

int main()
{
    Server svr;
    controller ctl;     //控制层
    /************************
     * 1.进行前端请求的获取(GET)及后端服务的推送(POST);
     ***********************/
    svr.set_base_dir("../MCIPclient_ivl/IVL_wwwroot");
    svr.listen("0.0.0.0",8080);
    return 0;
}

(2)MCIPserver_bll文件夹->BLL_view.hpp文件

#pragma once

#include<iostream>
#include<string>
#include<vector>
#include <ctemplate/template.h>
//按开发需求进行头文件的补充...

#include"./BLL_model.hpp"

namespace BLL_view
{
    using namespace BLL_model;
    /************************
     * 1.进行前端关键视图界面的渲染,如几大核心功能界面模块;
    ***********************/
    class view{
        public:
            view()
            {}
            ~view()
            {}
        public:
            //页面渲染函数接口
        private:  
            model mdl;
    };
}

(3)MCIPserver_bll文件夹->BLL_controller.hpp文件

#pragma once

#include<iostream>
#include<string>
#include<vector>
#include <jsoncpp/json/json.h>
//按开发需求进行头文件的补充...

#include"./BLL_view.hpp"
#include"./BLL_model.hpp"

namespace BLL_controller
{
    using namespace BLL_model;
    using namespace BLL_view;
    /************************
     * 1.接收请求、参数校验、调用应用层、返回结果;
     ***********************/
    class controller{
        public:
            controller()
            {}
            ~controller()
            {}
        public:
            //以请求情感分析模型为例,模拟数据流驱动过程
            std::string RequestSentimentAnalysisModel(/*言语数据及多模态标签*/)
            {
                //1.进行请求
                std::string result=mdl.SentimentAnalysisModelService(/*言语数据及多模态标签*/);
                //8.分析结果返回
                return result;
            }

            //其它请求函数接口
        private:
            model mdl;  
            view viw;  //视图层
    };
}

(4)MCIPserver_bll文件夹->BLL_model.hpp文件

#pragma once

#include<iostream>
#include<string>
#include<vector>
#include<unistd.h>
#include<cstdio>
#include<cstdlib>
//按开发需求进行头文件的补充...

#include"./MODEL_tl/TL_al.hpp"
#include"./MODEL_tl/TL_dl.hpp"
#include"./MODEL_tl/TL_tl.hpp"

namespace BLL_model
{
    using namespace TL_al;
    /************************
     * 1.将传统 MVC 的 “Model” 拆分为数据层、领域层、应用层,让每层专注单一职责,避免业务逻辑与数据处理混杂。
     ***********************/
    class model{
        public:
            model()
            {}
            ~model()
            {}
        public:     //调用数据层
            //负责数据CRUD,与数据库交互;
        public:     //调用领域层
            //封装核心业务规则;
        public:     //调用应用层
            //协调领域层与数据层,实现用户用例及核心功能;
            std::string SentimentAnalysisModelService(/*言语数据及多模态标签*/)
            {
                //2.调用应用层的相关模型函数接口
                std::string result=alm.processSentimentAnalysis(/*言语数据及多模态标签*/);
                //7.分析结果返回
                return result;
            }

        private:
            al_MultimodelProcessService alm;
    };
}

在文件夹MODEL_tl(模型-三层)下包括文件TL_al.hpp(应用层)、文件TL_dl.hpp(数据层)及文件TL_tl.hpp(领域层)。这三层从传统的 MVC 架构 “Model” 下进行拆分得来。在这里我们以文件TL_al.hpp(应用层)为例去简单展示后端数据流的业务逻辑情况,而文件TL_dl.hpp(数据层)及文件TL_tl.hpp(领域层)中的代码按示例进行相应开发书写即可。

(5)MCIPserver_bll文件夹->MODEL_tl文件夹->TL_al.hpp文件

#pragma once

#include<iostream>
#include<string>
#include<vector>
//按开发需求进行头文件的补充...

#include"../../MCIPserver_mms/MMS_SA/sa.hpp"

typedef int MultimodalLabel;

namespace TL_al
{
    using namespace sa;
    /************************
     * 1.model->应用层:多模型进程服务类
     * 通过调用该类中的功能函数接口,从而实现相应的AI模型服务;
     ***********************/
    class al_MultimodelProcessService{
        private:
            sa_text _sa_text;
            sa_voice _sa_voice;
            sa_image _sa_image;
            sa_video _sa_video;
            
        public:
            //情感分析(为例)
             std::string processSentimentAnalysis(std::string linguisticData,MultimodalLabel label)
             {
                //多模态标签为1->文本,标签为2->语音,标签为3->图像,标签为4->视频;
                if(label==1){
                    //3.调用相关模型,执行文本情感分析服务;
                    _sa_text.xxx(/*言语数据*/);
                    //6.分析结果返回
                }else if(label==2){
                    //3.调用相关模型,执行语音情感分析服务;
                    _sa_voice.xxx(/*言语数据*/);
                    //6.分析结果返回
                }else if(label==3){
                    //3.调用相关模型,执行图片情感分析服务;
                    _sa_image.xxx(/*言语数据*/);
                    //6.分析结果返回
                }else if(label==4){
                    //3.调用相关模型,执行视频情感分析服务;
                    _sa_video.xxx(/*言语数据*/);
                    //6.分析结果返回
                }
             }
            //手写体识别
             void processHandWriting(){}
             //机器翻译
             void processMachineTranslate(){}
            //语音合成
             void processLanguageSynthesis(){}
    };
    /************************
     * 2.model->应用层:...
     ***********************/
}

其次:在文件夹MCIPserver_mms(服务端-多模型服务)下包括我们整个系统多个多模态模型的文件。下面我们以情感分析文件夹MMS_SA(多模型服务-情感分析)为例,展示其下的sa.hpp(情感分析)文件,该文件将会根据相应的请求,通过API接口来调用该文件目录下相应的AI模型,从而实现用户的功能需求。

(6)MCIPserver_mms文件夹->MMS_SA文件夹->sa.hpp文件

#pragma once

#include<iostream>
#include<string>
//按开发需求进行头文件的补充...

namespace sa
{
    class sa_text{
        public:
            //4.相关模型函数API
            //5.模型分析后,得出相应的结果进行返回
        private:
    };
    class sa_voice{
        public:     
            //4.相关模型函数API
            //5.模型分析后,得出相应的结果进行返回
        private:
    };
    class sa_image{
        public:
            //4.相关模型函数API
            //5.模型分析后,得出相应的结果进行返回
        private:
    };
    class sa_video{
        public:
            //4.相关模型函数API
            //5.模型分析后,得出相应的结果进行返回
        private:
    };
}

2.关键改进点:让复杂业务逻辑“有处安放”

(1)引入“领域服务”封装核心业务逻辑

        对于传统 MVC 的 Model 层(如TranslationModel)既包含 “源文本、目标语言” 等数据,又包含 “调用 AI 模型、解析蒙古文语法” 等复杂逻辑,导致 Model 臃肿这些问题。所以我们通过“数据部分”和“逻辑部分”这两个模块去对其进行改进。数据部分采用实体类存储纯数据,如:MongolianText含content文本内容、encoding编码格式等属性,而无业务方法;逻辑部分用领域服务封装业务规则,其独立于数据仅处理逻辑。

// 1.数据层(纯数据)
class MongolianText {
private:
    std::string content; // 蒙古语文本内容
    std::string encoding; // 编码格式(如Unicode)
public:
    // get/set方法
    std::string getContent() const 
        { return content; }
    void setContent(const std::string& content)
        { this->content = content; }
    
    std::string getEncoding() const 
        { return encoding; }
    void setEncoding(const std::string& encoding) 
        { this->encoding = encoding; }
};


// 2.领域层(纯逻辑)
class SentimentResult;    // 前向声明情感分析结果类       
class MongolianSentimentAnalysisService {
public:
    // 蒙古语情感分析核心逻辑:结合AI模型与蒙古语语义规则
    SentimentResult analyze(const MongolianText& text);
};

// 情感分析结果类
class SentimentResult {
private:
    // 情感标签(假设为枚举类型,实际实现需定义)
    int sentimentLabel; // SentimentResult类
    double confidence;  // 置信度
public:
    SentimentResult(int sentimentLabel, double confidence) 
        : sentimentLabel(sentimentLabel), confidence(confidence) {}
    
    int getSentimentLabel() const 
        { return sentimentLabel; }
    double getConfidence() const 
        { return confidence; }
};

// 实现分析方法
SentimentResult MongolianSentimentAnalysisService::analyze(const MongolianText& text) {
    // 1. 调用AI模型获取初步结果
    // 2. 用蒙古语否定词规则修正结果(如"高兴"前加"不"变为"悲伤")
    // 3. 返回最终情感标签
    
    // 纯占位实现,实际逻辑需补充
    return SentimentResult(0, 0.0); // 假设0表示中性情感
}

(2)用“应用服务”串联跨领域流程

        对于复杂业务常涉及多步操作(如 “用户手写蒙古文→识别→翻译→语音合成”),传统 MVC 的 Controller 层直接写这些逻辑会导致代码冗长、复用性差这些问题。所以我们通过新增应用服务专门负责跨层/跨领域的流程协调,Controller 层仅调用应用服务,不写具体逻辑。

// 前向声明各类
class MongolianText;
class TranslationResult;
class ProcessResult;
class HandwritingRecognitionService;
class TranslationService;
class VoiceSynthesisService;
class HistoryRecordDataService;

// 应用服层(协调多步骤流程)
class MultimodalProcessService {
private:
    HandwritingRecognitionService* recognitionService; // 手写识别领域服务
    TranslationService* translationService; // 翻译领域服务
    VoiceSynthesisService* voiceService; // 语音合成领域服务
    HistoryRecordDataService* historyDataService; // 历史记录数据服务

public:
    // 构造函数(替代依赖注入)
    MultimodalProcessService(
        HandwritingRecognitionService* recognition,
        TranslationService* translation,
        VoiceSynthesisService* voice,
        HistoryRecordDataService* history
    ) : recognitionService(recognition), 
        translationService(translation),
        voiceService(voice),
        historyDataService(history) {}

    // 完整流程:手写→识别→翻译→语音合成→保存记录
    ProcessResult processHandwriting(const std::string& imageBase64);
};


// Controller层(仅调用应用层服务)
class MultimodalController {
private:
    MultimodalProcessService* processService;

public:
    // 构造函数
    MultimodalController(MultimodalProcessService* service) 
        : processService(service) {}

    // 处理请求的方法
    struct Result {
        bool success;
        ProcessResult* data;
        
        static Result success(ProcessResult* data) {
            return {true, data};
        }
    };
    Result process(const std::string& image);
};

(3)强化“数据层”与业务逻辑的解耦

        对于传统 MVC 中,Model 层常直接包含 SQL 操作,导致业务逻辑与数据库耦合(换数据库需改大量代码)这些问题。所以我们数据层用 Repository 模式封装数据库操作,对外提供抽象接口,屏蔽具体存储细节;因此领域层和应用层仅依赖 Repository 接口,不关心底层是 MySQL 还是 MongoDB。

// 翻译记录实体类
class TranslationRecord {
    // 类的具体实现保持不变
};
// 仓储接口(抽象数据操作)
class TranslationHistoryRepository {
public:
    virtual ~TranslationHistoryRepository() = default;
    virtual void save(const TranslationRecord& record) = 0; // 保存翻译记录
    virtual std::vector<TranslationRecord> findByUserId(const std::string& userId) = 0; // 查询用户历史
};

// MySQL实现(数据层细节)
class MysqlTranslationHistoryRepository : public TranslationHistoryRepository {
public:
    void save(const TranslationRecord& record) override {
        // 具体SQL逻辑:INSERT INTO ...
    }
    
    std::vector<TranslationRecord> findByUserId(const std::string& userId) override {
        // 具体SQL逻辑:SELECT * FROM ...
        return {};
    }
};


// 应用层(不依赖MySQL)
class TranslationHistoryService {
private:
    std::unique_ptr<TranslationHistoryRepository> repository; // 依赖接口,而非具体实现

public:
    explicit TranslationHistoryService(std::unique_ptr<TranslationHistoryRepository> repo)
        : repository(std::move(repo)) {}

    void saveRecord(const TranslationRecord& record) {
        repository->save(record); // 无需关心用什么数据库
    }
};

(4)引入“策略模式”处理多变业务规则

        对于蒙古语平台的业务规则可能多变,如翻译模型可能切换、情感分析算法可能升级等,传统 MVC 中硬编码规则会导致修改成本高这个问题。所以我们对多变的逻辑用策略模式封装为可替换的“策略”,通过配置动态选择,即支持“自研模型”和“第三方API”两种策略。

// 翻译策略接口(父类)
class TranslationStrategy {
public:
    virtual ~TranslationStrategy() = default;
    virtual std::string translate(const std::string& mongolianText, const std::string& targetLang) = 0;
};

// 策略1:自研翻译模型(子类)
class SelfDevelopedTranslationStrategy : public TranslationStrategy {
public:
    std::string translate(const std::string& mongolianText, const std::string& targetLang) override {
        // 具体实现逻辑
        return "自研模型翻译结果";
    }
};
// 策略2:第三方翻译API(子类)
class ThirdPartyTranslationStrategy : public TranslationStrategy {
public:
    std::string translate(const std::string& mongolianText, const std::string& targetLang) override {
        // 具体实现逻辑
        return "第三方API翻译结果";
    }
};


// 应用层动态选择策略
class TranslationService {
private:
    std::unique_ptr<TranslationStrategy> strategy;

public:
    // 构造时通过配置选择策略(如VIP用户用自研模型,普通用户用第三方)
    explicit TranslationService(const std::string& strategyType) {
        if (strategyType == "self") {
            strategy = std::make_unique<SelfDevelopedTranslationStrategy>();
        } else {
            strategy = std::make_unique<ThirdPartyTranslationStrategy>();
        }
    }

    std::string translate(const std::string& text, const std::string& targetLang) {
        return strategy->translate(text, targetLang); // 调用策略
    }
};

3.改进后架构对业务逻辑复杂平台的适配性

        通过 “拆分 Model 层为应用层 + 领域层 + 数据层”“引入 Repository 解耦存储”“用策略模式处理多变规则”,传统 MVC 被改造为 **“职责清晰、逻辑隔离、易于扩展”** 的架构,改进后的MVC架构图如下。其既能承载蒙古语平台的复杂业务逻辑、如:蒙古文特殊逻辑隔离处理、多模态功能协同交互、AI模型迭代集成等,又避免了代码臃肿和耦合问题。

改进的MVC架构图


网站公告

今日签到

点亮在社区的每一天
去签到