【架构进化】灵犀厨房四层分层设计给鸿蒙 App 搭一副坚不可摧的骨架摘要当你写完购物清单看着pages目录下横七竖八的十几个文件是不是觉得《灵犀厨房》越来越像一间堆满食材却找不到盐的厨房今天我们不写具体功能而是拿起“架构的手术刀”对整个项目做一次深度的分层重构。在这篇文章中我会用“四层装甲车”的比喻带你彻底搞懂 UI → ViewModel → Business → Services → Foundation 的依赖关系同时结合 HarmonyOS 6.1.0 的ObservedV2、ComponentV2等新特性绘制出一张攻守兼备的架构蓝图。读完你会发现——好的架构会让未来的每一行代码都写在正确的位置上。引言与系列定位在上一篇文章第 10 篇中我们顺利地把散落的勾选食材聚合成了一张漂亮的分组购物清单。但当我们得意地审视项目目录时一个危险的信号出现了pages/Index.ets里竟然同时揉杂了推荐算法、状态管理、甚至还有一段临时硬编码的模拟数据。这就像把菜刀、砧板、调料瓶全都丢进同一个水槽——看似方便一旦要加新功能整个厨房都会乱套。所以在应用正式上架申请成功后我们将向 Health Kit 健康数据发起冲锋前不过现在我们必须先停一停为《灵犀厨房》做一次彻底的“架构手术”。本文将交付一份可落地、可扩展的四层分层架构 v2.0它将彻底解决以下痛点代码耦合严重改一个 UI 却触发了业务逻辑崩溃状态管理随心所欲State、Link、Provide 满天飞模拟数据和真实服务混杂想接入 Health Kit 都无从下手读完之后你会清晰地知道什么样的代码该放进business/什么样的文件能直接触碰kit.HealthKit以及如何用 ViewModel 像胶水一样把 UI 与业务优雅粘合。核心原理与底层机制深度解读要理解这版架构的精髓我们不妨把《灵犀厨房》想象成一辆四层装甲车图 1外挂装甲UI 层负责抵挡用户的点击与滑动只关心“长什么样”绝不让一枚子弹穿透到内部。火控计算机ViewModel 层接收 UI 的指令计算并组织需要用到的数据但它不扣扳机。弹药系统Business 层真正的业务规则所在例如“从 10 道菜里筛出 4 道不辣且低于 500 大卡的推荐”。引擎与底盘Services 层封装最底层的系统能力比如调用 Health Kit、数据库、通知推送。它们只提供动力不关心你往哪儿开。零件图纸Foundation 层纯粹的数据结构像Recipe、UserPreference是全体模块的唯一语言。在 HarmonyOS 中这种分层之所以能生效靠的是依赖倒置和V2 状态管理的精确配合。ObservedV2装饰的 ViewModel 类就像指挥塔通过Trace属性把“弹药状态”实时同步给 UI 层的雷达屏幕。而 Business 层则完全不知道 UI 的存在它只是对着空气接口开火。这就保证了当我们后续将模拟厨电换成真实分布式软总线时只需要替换 Business 层的一个模块UI 层连一个像素都不会抖动。关键知识点详解面对中大型鸿蒙应用架构选型通常有三条路架构模式核心思想优点缺点《灵犀厨房》适用性MVVM 轻架构每个页面配一个 ViewModelModel 层直接操作数据简单、上手快业务逻辑容易在 ViewModel 中膨胀跨页面复用困难❌ 前期可用后期难以维护购物清单、健康分析等多模块交互VIPER/Clean Architecture严格的 Interactor、Presenter、Router 分离高度解耦可测试性极强模板代码过多对中小型应用性价比低❌ 团队只有你一人过度设计四层分层架构本文方案UI-ViewModel-Business-Services 清晰切分Foundation 作为数据基座兼具清晰边界与务实灵活符合鸿蒙组件化思想需要严格遵循依赖规则初期需要一定学习成本✅最佳平衡点完美适配《灵犀厨房》的功能增长曲线同时对比一下状态管理方案的进化方案装饰器性能类属性观测跨组件共享《灵犀厨房》v2.0 选型V1 状态管理State、Link、Provide等一般易触发冗余渲染不支持类属性级监听复杂且需手动Provide/Consume❌ 已在第 9 篇被 V2 替代V2 状态管理ObservedV2、Trace、Local、Param精准更新性能提升明显Trace可监听类成员变量通过Provider()/Consumer()简洁优雅✅ 本次架构重构的唯一选择架构设计 / 核心逻辑图解话不多说上“骨相图”。下面这张 Mermaid 关系图揭示了《灵犀厨房》v2.0 的五层依赖与四大数据流。Foundation 层Services 层Business 层UI 层 (pages/components)ViewModel 层MainContainerTab导航HomeViewModelRecipeDetailPageIngredientViewModelShoppingListPageShoppingListVMHealthDashboardHealthDashboardVMKitchenDeviceKitchenDeviceVMProfilePageProfileViewModelRecommendEngineRecipeManagerShoppingListNutritionAnalyzerKitchenDeviceSimulatorHealthServiceHelperNotificationHelperRelationalStoreHelperRecipeUserPreferenceMockData架构师解读注意所有依赖箭头都是从上往下且 Services 层绝不反向引用 Business 或 UI。这就奠定了“上层易变底层稳定”的演化基础。再来看一条最典型的推荐数据流是如何在四层间起舞的MockDataRecommendEngineHomeViewModelHomeTabContentMockDataRecommendEngineHomeViewModelHomeTabContentrefreshByPreference()isLoading truegetRecommendations(pref, 4)读取全量菜谱忌口过滤 卡路里筛选多维加权评分 (偏好季节去重)4条推荐Recipe数组recommendedRecipes result, isLoading falseTrace 触发精准渲染实战分层架构的落地与模块化搬迁架构图再漂亮不落地就是一张废纸。我们根据这张蓝图对《灵犀厨房》的工程目录做了一次精准的“器官移植”。Step 1重新定义 Foundation 层——让数据模型成为单一真相源首先把散落在各处的FoodItem、Recipe等类型统一收口到foundation/model/。这里不得存在任何import router或kit只能有纯血统的class和interface。// foundation/model/Recipe.etsexportclassRecipe{id:number0name:stringcover:Resource$r(app.media.default_cover)ingredientItems:IngredientItem[][]tags:string[][]calories:number0// ...}exportclassIngredientItem{name:stringamount:stringisChecked:booleanfalse}变化点解读相比第 4 篇时model/下的混乱现在的 Foundation 层连一个State都不允许出现。它就像国际度量衡局只负责定义“米”和“千克”绝不参与买卖。Step 2提取 Business 层——把“智慧大脑”独立出来将原来嵌在Index.ets中的推荐逻辑重构为business/RecommendEngine.ets的单例。同样的手术也用在菜谱管理、购物清单分组上。// business/RecommendEngine.etsimport{Recipe}from../foundation/model/Recipeimport{UserPreference}from../foundation/model/UserPreferenceimport{MockData}from../foundation/model/MockDataclassRecommendEngine{getRecommendations(pref:UserPreference,count:number):Recipe[]{// 1. 从 MockData 全量获取letcandidatesMockData.getAllRecipes()// 2. 忌口过滤candidatescandidates.filter(r!r.tags.some(tagpref.allergies.includes(tag)))// 3. 多维度评分排序...// 4. 去重并返回returncandidates.slice(0,count)}}exportconstrecommendEnginenewRecommendEngine()核心点解读现在即便我们把MockData替换为远端 API 或 Health Kit 实时数据也只需在这个黑盒内部修改。ViewModel 和 UI 完全无感。Step 3固实 ViewModel 管道——用 ObservedV2 粘合一切每个复杂页面搭配专属 ViewModel它只负责做两件事调用 Business 层获取数据以及用 Trace 属性驱动 UI 刷新。// viewmodel/HomeViewModel.etsimport{recommendEngine}from../business/RecommendEngineimport{Recipe}from../foundation/model/RecipeObservedV2exportclassHomeViewModel{TracerecommendedRecipes:Recipe[][]TraceisLoading:booleanfalserefreshByPreference(pref:UserPreference){this.isLoadingtruethis.recommendedRecipesrecommendEngine.getRecommendations(pref,4)this.isLoadingfalse}}Step 4UI 层瘦身——用 ComponentV2 Local 拥抱 ViewModelMainContainer内的每个 Tab 都变成了一个干净的ComponentV2仅持有自己的 ViewModel 实例并把它通过BuilderParam或组件树向下传递。// pages/MainContainer.ets 中 HomeTab 的片段ComponentV2struct HomeTabContent{LocalhomeVM:HomeViewModelnewHomeViewModel()build(){Column(){if(this.homeVM.isLoading){LoadingProgress()}else{List(){ForEach(this.homeVM.recommendedRecipes,(recipe:Recipe){ListItem(){RecommendCard({recipe:recipe})}})}}}}}变化点解读UI 层彻底扔掉了所有if-else业务判断它的build()方法就像一个哑巴服务员只负责端盘子不负责炒菜。Step 5Services 层预留接口——为 Health Kit 腾出空间我们在services/HealthServiceHelper.ets中预埋了一个桩Stub它目前返回模拟数据但完整实现了calculateNutritionBudget所需的一切签名。第 12 篇接入真实 Health Kit 时只需要填充其内部实现。运行与结果验证现在我们执行一次全量编译并通过 DevEco Studio 的依赖分析插件查看模块耦合度。期望输出在 Log 中通过代码显式打印验证分层是否生效[灵犀厨房-架构] 当前首页推荐引擎已独立加载依赖链: UI→HomeViewModel→RecommendEngine→MockData [灵犀厨房-架构] 未检测到 business 层对 kit.HealthKit 的直接引用分层规则校验通过。日志解读这串日志虽然是我们刻意埋下的“架构哨兵”但它真实地反映出四层分层的约束力。当我们后续新增 HealthKit 接入时如果发现编译报错Cannot find module kit.HealthKit出现在business/目录下就说明有人试图越界开火必须立刻修正。本阶段总结与下篇预告今天我们没有为《灵犀厨房》添加任何一个用户可见的新按钮但却完成了整个项目最昂贵的投资——架构。我们用四层装甲车的模型把脆弱的代码堆砌重构为 UI、ViewModel、Business、Services、Foundation 五大清晰阵地并依托 HarmonyOS 6.1.0 的 V2 状态管理实现了编译期的依赖约束和运行时的精准渲染。地基已经夯实到足以承载摩天大楼。这篇作为《灵犀厨房》架构补充篇。在后续等应用完成上架后我们将正式驾驶这辆装甲车冲进 【数据打通】访问 Health Kit 获取健康数据的战场。届时你会看到HealthServiceHelper如何从 Stub 蜕变成真正的健康数据管道而你的菜谱推荐也将第一次拥有卡路里和步数的科学依据。我们下期见 本系列持续更新中下一篇我们将完成【营养分析引擎】计算个性化卡路里建议新篇章敬请期待。专栏入口[《从0到1开发灵犀厨房App》合集] | ⭐源码Gitee 仓库