Harmony 开发中的三层架构

三层工程结构 是鸿蒙应用开发中推荐的 模块化分层架构 ,主要用于复杂应用的代码组织,强调模块解耦复用性 。这一架构与操作系统内核的分层不同,聚焦于 应用工程本身的结构设计。以下是详细的层级说明、依赖规则和实际应用场景分析:


三层工程结构

  • commons(公共能力层):用于存放公共基础能力集合(如工具库、公共配置等)。commons层可编译成一个或多个HAR包或HSP包,只可以被products和features依赖,不可以反向依赖。

  • features(基础特性层):用于存放基础特性集合(如应用中相对独立的各个功能的UI及业务逻辑实现等)。各个feature高内聚、低耦合、可定制,供产品灵活部署。不需要单独部署的feature通常编译为HAR包或HSP包,供products或其它feature使用。需要单独部署的feature通常编译为Feature类型的HAP包,和products下Entry类型的HAP包进行组合部署。features层可以横向调用及依赖common层,同时可以被products层不同设备形态的HAP所依赖,但是不能反向依赖products层。

  • products(产品定制层):用于针对不同设备形态进行功能和特性集成。products层各个子目录各自编译为一个Entry类型的HAP包,作为应用主入口。products层不可以横向调用。

上方的图和解释来源于鸿蒙官方文档 详情看这里鸿蒙三层架构官方文档,下边是自己进行的一个总结,如果有错误欢迎指出。

一、三层工程结构定义

graph TD A[commons] -->|被依赖| B[features] A -->|被依赖| C[products] B -->|被依赖| C B -->|横向依赖| B

1. commons(公共能力层)

  • 定位 :基础能力沉淀层,存放 全局共享工具、通用组件、基础服务
  • 输出形式 :编译为 HAR(静态共享包)HSP(动态共享包)
  • 依赖规则
    • 不可被反向依赖:commons 层不依赖上层(features/products)。
    • 禁止业务逻辑:仅包含与业务无关的公共代码。

典型内容

  • 工具类:LoggerNetworkUtilsStorageHelper
  • 通用组件:自定义按钮、弹窗模板
  • 基础配置:全局样式、路由表

代码示例

typescript 复制代码
// commons/src/main/ets/utils/Logger.ets
export class Logger {
  static info(message: string): void {
    console.log(`[INFO] ${message}`);
  }
}

2. features(基础特性层)

  • 定位 :功能模块集合层,每个模块 高内聚、可独立运行/测试
  • 输出形式
    • 非独立部署:编译为 HAR/HSP 供其他模块复用。
    • 独立部署 :编译为 Feature 类型 HAP(动态按需加载)。
  • 依赖规则
    • 可横向依赖:不同 feature 模块可互相调用。
    • 可向下依赖:可引用 commons 层。
    • 不可向上依赖:禁止依赖 products 层。

典型内容

  • 用户模块:user(登录、个人中心)
  • 支付模块:payment(订单、支付)
  • 内容模块:content(文章、视频)

代码示例

typescript 复制代码
// features/user/src/main/ets/LoginPage.ets
import { Logger } from '@commons/utils/Logger';

@Entry
@Component
struct LoginPage {
  build() {
    Column() {
      Button('登录')
        .onClick(() => {
          Logger.info('登录按钮点击');
        })
    }
  }
}

3. products(产品定制层)

  • 定位 :设备形态适配层,针对不同设备(手机、手表、平板)整合功能模块
  • 输出形式 :编译为 Entry 类型 HAP(应用主入口)。
  • 依赖规则
    • 不可横向依赖:不同 product 模块间隔离。
    • 可向下依赖:可引用 features 和 commons 层。

典型内容

  • phone:手机端入口,整合全功能。
  • watch:手表端入口,仅集成核心功能。
  • tablet:平板端入口,适配大屏布局。

代码示例

typescript 复制代码
// products/phone/src/main/ets/MainAbility.ets
import { LoginPage } from '@features/user';

@Entry
@Component
struct MainAbility {
  build() {
    LoginPage(); // 直接复用 feature 模块
  }
}

二、依赖关系与编译配置

1. 模块依赖声明

在模块的 oh-package.json5 中声明依赖:

json 复制代码
// features/user/oh-package.json5
{
  "dependencies": {
    "@commons/utils": "file:../../commons/utils" // 依赖 commons 层
  }
}

2. 编译类型配置

在模块的 build-profile.json5 中定义输出类型:

json 复制代码
// products/phone/build-profile.json5
{
  "apiType": "entry", // 标记为 Entry 类型 HAP
  "buildOption": {
    "artifactType": "hap"
  }
}

三、实际应用场景

场景 1:多设备适配

  • 手机端products/phone):集成所有 features。
  • 手表端products/watch):仅集成 user 和基础功能。

场景 2:动态功能加载

  • 将低频功能(如 payment)编译为 Feature HAP,用户使用时按需下载。

场景 3:团队协作

  • 不同团队负责独立 feature 模块,通过 HAR/HSP 共享代码。

四、优势与最佳实践

优势 实现方式
模块解耦 严格依赖规则(禁止反向/循环依赖)
代码复用 通过 HAR/HSP 共享公共代码
灵活部署 Entry HAP + Feature HAP 组合
编译加速 独立模块增量编译

最佳实践

  1. 避免跨层直调:通过接口或事件通信,而非直接引用。
  2. 版本统一管理 :使用 ohpm 管理公共库版本。
  3. 按需拆包:对高频功能使用 HSP 动态加载。

五、常见错误示例

错误 1:反向依赖

typescript 复制代码
// commons 层错误依赖 feature
import { LoginService } from '@features/user'; // ❌ 违反依赖规则

错误 2:循环依赖

graph TD A[featureA] -->|依赖| B[featureB] B -->|依赖| A

解决方案:将公共逻辑下沉至 commons 层。


相关推荐
Pigwantofly9 小时前
鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)
android·华为·harmonyos
别说我什么都不会13 小时前
OpenHarmony 实战开发 —— 在自绘编辑框中使用输入法
嵌入式·harmonyos
Georgewu14 小时前
【HarmonyOS 5】鸿蒙实现手写板
前端·华为·harmonyos
御承扬18 小时前
从零开始开发纯血鸿蒙应用之语音输入
华为·harmonyos
Georgewu20 小时前
【HarmonyOS 5】敏感信息本地存储详解
前端·harmonyos
娅娅梨21 小时前
HarmonyOS-ArkUI V2装饰器-@Once
华为·harmonyos·arkts·arkui·移动端开发
别说我什么都不会1 天前
OpenHarmony 实战开发 —— 实现一个输入法应用
harmonyos
别说我什么都不会1 天前
OpenHarmony 实战开发 —— IPC通信开发指南(C/C++)
网络协议·harmonyos
少年的云河月1 天前
OpenHarmony Camera开发指导(二):相机设备管理(ArkTS)
harmonyos·openharmony·camera·相机开发
枫叶丹41 天前
【HarmonyOS Next之旅】DevEco Studio使用指南(十三) -> ArkTS/TS代码重构
华为·harmonyos·deveco studio·harmonyos next