1. Repository模式核心概念与离线场景适用性

1.1 模式定义与架构本质

定义:Repository 是在领域层定义的一种机制,负责封装存储、检索和检索行为,它模拟了一个集合(Collection)的概念。这是 Eric Evans 在《领域驱动设计》中提出的核心模式。

架构本质:Repository 并不是简单地与数据库交互,而是一种将领域实体与聚合根从具体的数据持久化技术(SQL、NoSQL、文件系统、缓存)中解耦的策略。这使得领域逻辑能够专注于业务规则,而不必关心数据在何处存储或如何读取。

离线关联:在离线环境下,数据源可能是本地的 SQLite、文件或内存缓存。Repository 就像一个统一的数据管理员,业务代码无需感知此刻数据是来自远程服务器还是本地缓存。

核心价值: 引入抽象屏障,使得领域层无需依赖具体数据库驱动或网络框架。在线与离线数据源的切换对业务逻辑透明。
Repository 模式离线分层架构与数据流 领域层 (实体/聚合) Repository 接口 (抽象屏障) Repository 实现在线 Repository 实现离线 远程数据源 (API) 本地数据源 (DB/文件) 信任边界:领域层定义契约,数据层满足契约,实现双向解耦。

1.2 离线场景下的数据需求挑战

  • 网络不可达:用户在弱网或无网状态下操作时,应用必须优雅降级,不能崩溃或无限期挂起。
  • 数据新鲜度:必须定义策略是“本地缓存优先”还是“远程获取优先”,并处理缓存过期问题。
  • 写入冲突:离线环境下用户对数据进行修改,网络恢复后需要协调这些变更,避免数据覆盖或丢失。
  • 存储容量:移动端或边缘设备存储空间有限,需要制定数据驱逐策略(LRU、TTL)。

1.3 领域层与数据层分离的架构意义

依赖倒置原则(DIP):高层模块(领域)不应依赖于低层模块(数据基础设施)。两者都应依赖于抽象。Repository 模式正是这一原则的典型应用。

信任链路:领域层信任 Repository 接口定义的集合语义,数据层信任 Repository 实现规范。接口由领域层定义,由数据层遵守。

控制流与数据流:控制流从领域层流经 Repository 到达数据源,但依赖流方向相反(领域层定义接口,数据层实现接口)。这使得领域层完全独立于数据技术。

1.4 核心组件职责与边界

组件 核心职责 边界位置 数据流示例
领域实体/聚合 封装业务状态与行为。 纯内存对象,属于领域层。 向 Repository 发送 save(user) 或 findById(id)
Repository 接口 定义集合语义(CRUD 操作)。 属于领域层,不引用数据源 API。 interface UserRepository { find, save, delete }
Repository 实现 将接口调用路由到具体数据源。 属于数据基础设施层。 转发 findById 到 CacheDataSource 或 ApiDataSource
本地数据源 管理离线存储(SQLite, File, MMKV)。 数据层。 返回本地数据或缓存远程数据。
远程数据源 管理网络请求(REST, GraphQL)。 数据层。 用户在线时获取最新数据。

1.5 架构方案权衡与风险点

  • 选型权衡:
    • 纯粹的抽象会带来轻微的运行时调度开销。
    • 维护多套实现(在线/离线)会增加前期开发成本。
    • 接口粒度(粗粒度 vs. 细粒度)直接影响复杂性与灵活性。
  • 风险点:
    • 泄漏抽象:Repository 的实现细节泄漏到领域层。例如领域层需要关心 FetchPolicy.REMOTE_FIRST 或序列化方式。
    • 过度设计:对于只有远程数据库且无离线需求的简单 CRUD 场景,强行引入多层抽象反而增加维护成本。
    • 同步灾难:如果离线写入冲突未能妥善处理(如未使用冲突检测策略),会造成数据永久不一致。
架构警告: 不要为了让 Repository 模式工作而将领域实体退化为仅包含 Getter/Setter 的 DTO。领域实体应包含职责内聚的业务行为。Repository 的职责是返回领域对象,而不是原始数据集或数据行。

1.6 落地步骤与验收标准

落地步骤:

  1. 识别聚合:在领域模型中明确聚合根与边界上下文。
  2. 定义接口:在领域层模块中定义 Repository 接口,方法签名使用领域对象。
  3. 抽象数据源:定义数据源接口(例如 UserLocalDataSource、UserRemoteDataSource)。
  4. 实现组装:在数据基础设施层实现 Repository 接口,组合调用各种数据源。
  5. 依赖注入:通过 IoC 容器将具体实现挂接到领域层。

验收标准:

  • 领域层代码零引用数据库驱动、网络库或具体序列化框架。
  • 切换数据源时(例如从内存切换到 SQLite),无需修改领域层任何代码。
  • 领域逻辑可独立测试,无需搭建数据库或网络 Mock 环境。