文章

跨端架构设计模式深度解析

跨端架构模式:MVVM、Redux/Bloc、Clean Architecture 与模块化在跨端项目的落地。 讲清各模式职责划分,掌握后能答出「大型跨端 App 怎么分层」。

跨端架构设计模式深度解析

一句话概括

跨端架构的核心不是选哪个库,而是解决”状态从哪里来、往哪里去、谁来通知 UI”这个三角问题——理解了状态流转路径,BLoC/Riverpod/Redux 都只是这个路径的不同实现。

核心知识点

1. 状态管理的本质:三个角色一场戏

1
2
3
4
5
6
7
8
// 任何一个状态管理方案都在回答三个问题:
// ① 谁持有状态?(Store / Notifier / Bloc)
// ② 怎么变状态?(dispatch / emit / state = newState)
// ③ 谁通知 UI 刷新?(Consumer / BlocBuilder / useSelector)

// 这个模式比你想象的要简单:
// 用户操作 → 发送意图 → 产出新状态 → UI 自动响应
// 不同框架只是这三个环节的语法糖不同

2. Clean Architecture 为何在跨端特别重要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 核心原则:业务逻辑中不能出现一行 Flutter/RN 的 import
// ❌ 反过来就错了——UI 层可以依赖业务层,业务层绝不能依赖 UI 层

// Domain 层:纯 Dart/TS,不 import 任何框架
abstract class OrderRepository {
  Future<Order> create(Cart cart, Address addr);
}

class CheckoutUseCase {
  final OrderRepository repo;
  CheckoutUseCase(this.repo);
  
  Future<CheckoutResult> execute(Cart cart) async {
    // 库存检查 → 支付 → 创建订单,纯业务逻辑
    // 这段代码可以在任何框架里跑,单元测试一行 mock 就够
  }
}

3. 三层对比:RN vs Flutter vs ArkUI 的架构偏好

1
2
3
4
5
6
7
8
9
10
11
// RN:社区野蛮生长,没有官方推荐
//   → Redux Toolkit / Zustand / Jotai 三足鼎立
//   → 选 Redux 的原因通常是"团队会",不是"项目需要"

// Flutter:Google 刻意模糊标准答案
//   → BLoC 曾被视为正统,但 Riverpod 已经追平甚至超过
//   → 选 BLoC 的理由:事件可追溯 + 大团队强制规范
//   → 选 Riverpod 的理由:更少模板代码 + AsyncValue 天然支持 loading/error/data

// ArkUI:华为提供 @State/@Provide/@Consume 装饰器
//   → 适合中小型应用,大型项目仍需要引入类似 MVVM 的分层

4. 模块化:”按功能分层”而不是”按类型分包”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ❌ 初学者最爱(按类型):
components/  ← 100 个组件扔一起
screens/     ← 50 个页面扔一起
services/    ← 30 个 service 扔一起

// ✅ 正确姿势(按功能):
features/auth/     ← 登录注册的全部东西在这
  ├── domain/      ← entities + usecases
  ├── data/        ← repositories + datasources
  └── presentation/ ← pages + widgets + providers
features/feed/
features/chat/

// 核心判断:删掉一个功能时,只删一个目录就行

5. 平台适配:策略模式,不是 if-else 堆砌

1
2
3
4
5
6
7
8
9
10
11
// ❌ 散落各处的 Platform.isIOS 判断
if (Platform.isIOS) { /* 10 行 */ }
if (Platform.isAndroid) { /* 8 行 */ }

// ✅ 统一 adapter 层 + 策略模式
abstract class PlatformNavigator {
  void openSettings();
}
class IOSNavigator implements PlatformNavigator { ... }
class AndroidNavigator implements PlatformNavigator { ... }
// 全项目只有一个地方决定用哪个实现

其实你每天都在用

  • React Navigation 的 push/pop:背后是原生 UINavigationController / FragmentManager 的桥接调用,不是你 JS 线程里的操作
  • **Provider.of(context)**:本质是 Flutter 的 InheritedWidget,沿着 Element 树往上找,找到最近的那个类型——跟 React Context 一个思路
  • Redux 的 reducer:跟 Array.reduce 完全一样的模式,(prevState, action) => nextState,只是加了订阅机制
  • get_it 依赖注入:一个全局 Map<Type, Object>,注册时放进去,用时取出来——Service Locator 模式,简单粗暴但有效
  • ArkUI 的 @Consume:跟 Flutter 的 InheritedWidget 几乎一样的思路,祖先提供数据、后代订阅消费,不需要 props 逐层透传

常见误解(FAQ)

❌ 误区一:”状态管理选错了,项目就完了”

这是一个被过度贩卖的焦虑。实际上,只要你把业务逻辑从 UI 中抽离(哪怕只是一个简单的分离),后续换方案的成本并不高。Redux → Zustand、BLoC → Riverpod 的迁移通常只需要改 Provider 声明和 UI 消费方式,Domain 层完全不动。关键是分层,不是选库。

❌ 误区二:”Clean Architecture 能让代码自动变好”

Clean Architecture 只是结构约束,不是质量保证。如果 UseCase 里写满了 await Future.delayed() 等假逻辑、Entity 只是一个 map 的包装、Data 层的错误处理全是 catch(e) { return null }……那 Clean Architecture 只是把烂代码搬到了更深的目录里。

❌ 误区三:”Redux 性能差,不要用”

Redux 本身不慢——selector 机制配合 shallowEqual 可以精准控制 rerender 范围。让人感觉慢的通常是:① 把整个 App 状态塞一个 reducer 里;② 没用 createEntityAdapter 管理列表;③ selector 里做了昂贵的计算而不是用 createSelector 缓存。

❌ 误区四:”ArkUI 太新了,架构不成熟”

ArkUI 的 @State/@Link/@Provide/@Consume 装饰器体系其实借鉴了 SwiftUI 和 Compose 的声明式 UI 思想。它在响应式粒度上的设计比 RN 的 setState 更先进。真正不成熟的是社区生态(第三方架构库少),不是框架本身。

一句话总结

跨端架构的精髓不在于”用哪种模式最好”,而在于变化发生时,你需要改多少代码——好的架构让变化只触及边界,差的架构让变化传播到全项目。

本文由作者按照 CC BY 4.0 进行授权