当前位置:首页 > 技术 > 正文内容

基于职责分离的模块化设计——图书管理系统的实现

访客 技术 2026年7月15日 1

软件功能的三类核心逻辑

在开发一个完整的应用程序时,代码通常可以划分为三个关键部分:

  • 展示逻辑:负责界面渲染和信息输出。例如将图书列表以表格形式打印到控制台。
  • 业务逻辑:专注于数据操作本身,如在容器中插入、删除或查找记录,不关心用户如何输入或结果如何呈现。
  • 控制逻辑:作为桥梁,接收用户指令,调用相应的处理函数,并根据执行结果决定下一步的交互行为。

以"添加图书"功能为例,若将所有步骤混杂在一个函数中实现,虽然直观,但会导致结构混乱、难以测试与复用。尤其当多个功能都需要访问相同的数据结构时,过度依赖全局变量会使程序耦合严重,维护成本陡增。

采用模块化策略进行重构

应按照单一职责原则,将上述三类逻辑拆分为独立的函数单元。针对"添加图书"场景,可定义以下接口:

void EnterAddMode(BookCollection* library); // 启动添加流程,含交互与展示
int InsertBook(BookCollection* library, const BookItem* newBook); // 单纯执行插入操作

其中,InsertBook 函数仅关注数据层面的操作:

  • 返回值表示操作状态:-2 表示书籍已存在;-1 表示内存分配失败;非负整数为成功插入的位置索引。
  • 不涉及任何输入输出操作,也不引用任何全局数据结构。

分层协作的伪代码实现

1. 功能入口函数 EnterAddMode

EnterAddMode(BookCollection* library)
{
  // 展示当前馆藏
  DisplayAllBooks(library);

  // 收集用户输入并构建新书对象
  BookItem inputBook = CollectBookInfoFromUser();

  // 执行核心插入操作
  int result = InsertBook(library, &inputBook);

  // 根据返回状态反馈给用户
  if (result < 0) {
    ShowErrorMessage(result == -1 ? "内存不足" : "该书已存在");
  } else {
    PrintSuccess("添加成功", result);
    RenderBookDetail(&inputBook);  // 调用专用格式化显示函数
  }

  // 询问是否继续
  if (AskUser("继续添加?")) {
    EnterAddMode(library);  // 递归调用自身
  }
}

2. 主循环设计

MainLoop()
{
  BookCollection* library = LoadLibraryData();  // 初始化数据源

  while (true) {
    ShowMainMenu();                     // 输出主菜单界面
    int choice = GetUserChoice();       // 获取用户选择

    switch (choice) {
      case 1:
        DisplayAllBooks(library);
        break;
      case 2:
        EnterAddMode(library);
        break;
      case 3:
        SearchBooks(library);
        break;
      default:
        HandleInvalidInput();
        break;
    }
  }
}

模块化带来的优势

通过清晰划分职责,实现了以下改进:

  • 每个函数职责明确,易于理解和测试。
  • 函数体简洁,避免了冗长过程。
  • 消除对全局状态的依赖,提升可维护性。
  • 关键功能如 DisplayAllBooksInsertBook 可被多处复用。

这种设计模式体现了控制器(控制流)、模型(数据处理)与视图(界面展示)之间的松耦合关系,为后续扩展提供了良好基础。

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。