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

-
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层不可以横向调用。
上方的图和解释来源于鸿蒙官方文档 详情看这里鸿蒙三层架构官方文档,下边是自己进行的一个总结,如果有错误欢迎指出。
一、三层工程结构定义
1. commons(公共能力层)
- 定位 :基础能力沉淀层,存放 全局共享工具、通用组件、基础服务。
- 输出形式 :编译为 HAR(静态共享包) 或 HSP(动态共享包)。
- 依赖规则 :
- 不可被反向依赖:commons 层不依赖上层(features/products)。
- 禁止业务逻辑:仅包含与业务无关的公共代码。
典型内容:
- 工具类:
Logger
、NetworkUtils
、StorageHelper
- 通用组件:自定义按钮、弹窗模板
- 基础配置:全局样式、路由表
代码示例:
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 组合 |
编译加速 | 独立模块增量编译 |
最佳实践:
- 避免跨层直调:通过接口或事件通信,而非直接引用。
- 版本统一管理 :使用
ohpm
管理公共库版本。 - 按需拆包:对高频功能使用 HSP 动态加载。
五、常见错误示例
错误 1:反向依赖
typescript
// commons 层错误依赖 feature
import { LoginService } from '@features/user'; // ❌ 违反依赖规则
错误 2:循环依赖
解决方案:将公共逻辑下沉至 commons 层。