HarmonyOS 组件设计模式应用:从理论到 ArkUI 实战的系统性指南
文章目录

每日一句正能量
“不要去证明自己值得被爱,需要你拼命证明的都不是真正的爱”
真正的爱不需要考试。需要你不断交答卷、通过考核才能得到的,那不是爱,是交易。值得被爱不需要证明,因为你本来就值得。需要你削足适履去匹配的,说明那个鞋本身就不合你的脚。爱是认出你本就珍贵,不是等你证明才珍贵。
一、引言:设计模式不是银弹,但缺了它寸步难行
在 HarmonyOS ArkUI 开发中,开发者常常面临这样的困境:一个自定义组件随着需求迭代越来越臃肿,状态管理逻辑与UI渲染代码纠缠不清,多端适配代码充斥着 if-else 分支,跨组件通信通过层层回调传递导致维护成本激增。这些问题的根源往往不是技术能力不足,而是缺乏系统性的架构设计思维。
设计模式(Design Patterns)是软件工程领域经过数十年验证的解决方案模板。在 ArkUI 声明式框架下,经典设计模式并非生搬硬套,而是需要结合 ArkTS 的语言特性和 ArkUI 的响应式机制进行本土化改造。本文将系统梳理六种核心设计模式在 ArkUI 组件开发中的实战应用,涵盖组合模式、观察者模式、策略模式、工厂模式、单例模式和装饰器模式,并辅以完整的生产级代码示例。
二、ArkUI 组件设计模式全景图
在 HarmonyOS 生态中,不同的设计模式解决不同层面的架构问题:

| 设计模式 | 核心解决的问题 | ArkUI 中的载体 |
|---|---|---|
| 组合模式 | 复杂组件的层级拆解与复用 | @BuilderParam 插槽机制 |
| 观察者模式 | 状态变更的自动通知与响应 | @State/@Observed/EventHub |
| 策略模式 | 运行时行为切换与多端适配 | 策略接口 + 运行时选择器 |
| 工厂模式 | 动态组件创建与类型解耦 | 工厂函数 + 类型映射表 |
| 单例模式 | 全局唯一状态与资源共享 | 私有构造函数 + 静态实例 |
| 装饰器模式 | 组件能力增强与行为包装 | 高阶组件 + @BuilderParam |
三、组合模式:组件复合与插槽机制
3.1 模式核心思想
组合模式(Composite Pattern)定义了如何将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。在 ArkUI 中,这一模式通过 @BuilderParam 插槽机制得到原生支持。

3.2 实战:可插槽的页面布局框架
// 定义布局组件接口
interface LayoutSlot {
header?: () => void;
content: () => void;
footer?: () => void;
sidebar?: () => void;
}
@Component
export struct PageLayout {
@Prop title: string = '';
@Prop showHeader: boolean = true;
@Prop showFooter: boolean = true;
@Prop showSidebar: boolean = false;
// 插槽定义:使用 @BuilderParam 实现组合模式
@BuilderParam headerBuilder: () => void = this.defaultHeader;
@BuilderParam contentBuilder: () => void;
@BuilderParam footerBuilder: () => void = this.defaultFooter;
@BuilderParam sidebarBuilder: () => void = this.defaultSidebar;
@Builder
defaultHeader() {
Row() {
Text(this.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
Blank()
Image($r('app.media.ic_more'))
.width(24)
.height(24)
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
.backgroundColor('#FFFFFF')
}
@Builder
defaultFooter() {
Row() {
Text('© 2026 HarmonyOS')
.fontSize(12)
.fontColor('#999999')
}
.width('100%')
.height(48)
.justifyContent(FlexAlign.Center)
.backgroundColor('#F5F5F5')
}
@Builder
defaultSidebar() {
Column() {
Text('侧边栏')
.fontSize(14)
.fontColor('#666666')
}
.width(200)
.height('100%')
.backgroundColor('#FAFAFA')
}
build() {
Column() {
if (this.showHeader) {
this.headerBuilder();
}
Row() {
if (this.showSidebar) {
this.sidebarBuilder();
}
Column() {
this.contentBuilder();
}
.layoutWeight(1)
.height('100%')
}
.layoutWeight(1)
.width('100%')
if (this.showFooter) {
this.footerBuilder();
}
}
.width('100%')
.height('100%')
}
}
// 使用示例:不同页面复用同一布局框架
@Entry
@Component
struct HomePage {
@Builder
homeContent() {
List() {
ListItem() { Text('推荐内容1') }
ListItem() { Text('推荐内容2') }
ListItem() { Text('推荐内容3') }
}
}
@Builder
homeHeader() {
Row() {
Search({ placeholder: '搜索内容' })
.width('80%')
Image($r('app.media.ic_notice'))
.width(24)
.height(24)
}
.width('100%')
.height(56)
.padding({ left: 16, right: 16 })
}
build() {
PageLayout({
title: '首页',
headerBuilder: this.homeHeader,
contentBuilder: this.homeContent,
showSidebar: false
})
}
}
@Entry
@Component
struct AdminPage {
@Builder
adminContent() {
Grid() {
// 管理后台仪表盘
}
}
@Builder
adminSidebar() {
Column() {
Text('用户管理').fontSize(14)
Text('订单管理').fontSize(14)
Text('数据统计').fontSize(14)
}
.width(200)
.padding(16)
}
build() {
PageLayout({
title: '管理后台',
contentBuilder: this.adminContent,
sidebarBuilder: this.adminSidebar,
showSidebar: true
})
}
}
3.3 组合模式的设计要点
- 统一接口:容器组件和叶子组件对外暴露一致的
@BuilderParam接口 - 默认实现:为每个插槽提供默认的
@Builder实现,降低使用门槛 - 条件渲染:通过布尔属性控制容器的显隐,而非在插槽内部判断
- 职责分离:布局逻辑在容器组件中,内容逻辑在使用方组件中
四、观察者模式:状态响应与事件驱动
4.1 模式核心思想
观察者模式(Observer Pattern)定义了对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会自动收到通知并更新。ArkUI 的 @State/@Observed 装饰器本身就是观察者模式的框架级实现,而 EventHub 则提供了业务层的观察者模式支持。

4.2 ArkUI 框架级观察者:@State 与 @Observed
@Observed
class UserProfile {
name: string = '';
avatar: string = '';
level: number = 1;
isVip: boolean = false;
}
@Component
struct UserCard {
// @ObjectLink 建立对嵌套对象的观察
@ObjectLink user: UserProfile;
// 观察者:当 user 的任何属性变更时,自动重渲染
build() {
Row({ space: 12 }) {
Image(this.user.avatar)
.width(48)
.height(48)
.borderRadius(24)
Column({ space: 4 }) {
Text(this.user.name)
.fontSize(16)
.fontWeight(FontWeight.Medium)
Row({ space: 8 }) {
Text(`Lv.${this.user.level}`)
.fontSize(12)
.fontColor('#999999')
if (this.user.isVip) {
Text('VIP')
.fontSize(10)
.fontColor('#FFD700')
.backgroundColor('#FFF8E1')
.padding({ left: 6, right: 6, top: 2, bottom: 2 })
.borderRadius(4)
}
}
}
.alignItems(HorizontalAlign.Start)
.layoutWeight(1)
}
.width('100%')
.padding(16)
.backgroundColor('#FFFFFF')
.borderRadius(8)
}
}
@Component
struct UserProfilePage {
@State user: UserProfile = new UserProfile();
aboutToAppear() {
// 模拟异步加载用户数据
setTimeout(() => {
this.user.name = 'HarmonyDev';
this.user.avatar = 'https://example.com/avatar.png';
this.user.level = 5;
this.user.isVip = true;
// 所有使用 @ObjectLink 观察 user 的组件会自动刷新
}, 1000);
}
build() {
Column() {
UserCard({ user: this.user })
UserStats({ user: this.user }) // 另一个观察者
UserSettings({ user: this.user }) // 又一个观察者
}
}
}
4.3 业务级观察者:EventHub 事件中心
// EventHub.ets —— 类型安全的事件中心
class EventHub {
private static instance: EventHub | null = null;
private handlers: Map<string, ((data: Object) => void)[]> = new Map();
private constructor() {}
static getInstance(): EventHub {
if (!EventHub.instance) {
EventHub.instance = new EventHub();
}
return EventHub.instance;
}
on<T>(eventName: string, callback: (data: T) => void): () => void {
const list = this.handlers.get(eventName) || [];
list.push(callback as (data: Object) => void);
this.handlers.set(eventName, list);
return () => this.off(eventName, callback);
}
once<T>(eventName: string, callback: (data: T) => void): void {
const wrapper = (data: T) => {
callback(data);
this.off(eventName, wrapper);
};
this.on(eventName, wrapper);
}
emit<T>(eventName: string, data?: T): void {
const list = this.handlers.get(eventName) || [];
list.forEach(cb => {
try {
cb(data as Object);
} catch (e) {
console.error(`[EventHub] ${eventName} handler error:`, e);
}
});
}
off<T>(eventName: string, callback: (data: T) => void): void {
const list = this.handlers.get(eventName) || [];
this.handlers.set(eventName, list.filter(cb => cb !== callback));
}
}
// 使用示例:购物车跨页面通信
@Component
struct ShoppingCartBadge {
@State badgeCount: number = 0;
private eventHub = EventHub.getInstance();
private unsubscribe?: () => void;
aboutToAppear() {
this.unsubscribe = this.eventHub.on<number>('cart:updated', (count) => {
this.badgeCount = count;
});
}
aboutToDisappear() {
this.unsubscribe?.();
}
build() {
Badge({ value: this.badgeCount.toString(), position: BadgePosition.RightTop }) {
Image($r('app.media.ic_cart'))
.width(28)
.height(28)
}
}
}
// 商品详情页触发事件
@Component
struct ProductDetail {
private eventHub = EventHub.getInstance();
addToCart() {
// 业务逻辑...
const newCount = 3; // 假设购物车已有3件
this.eventHub.emit('cart:updated', newCount);
}
}
4.4 观察者模式使用约束
- 避免循环依赖:A 观察 B,B 观察 A 会导致无限递归通知
- 及时取消订阅:在
aboutToDisappear()中清理事件监听,防止内存泄漏 - 控制通知粒度:避免在循环中频繁触发状态变更,使用批量更新
- 异常隔离:事件处理中的异常不应影响其他观察者
五、策略模式:多端适配与行为切换
5.1 模式核心思想
策略模式(Strategy Pattern)定义了一系列算法,并将每个算法封装起来,使它们可以互相替换。在 HarmonyOS 多端适配场景中,策略模式是消除 if-else 分支的利器。

5.2 实战:多端布局策略
// 策略接口
interface LayoutStrategy {
getColumns(): number;
getGutter(): number;
getPadding(): Padding;
getNavPosition(): 'top' | 'bottom' | 'side';
getFontScale(): number;
}
// 手机策略
class PhoneStrategy implements LayoutStrategy {
getColumns(): number { return 1; }
getGutter(): number { return 8; }
getPadding(): Padding { return { left: 16, right: 16 }; }
getNavPosition(): 'top' | 'bottom' | 'side' { return 'bottom'; }
getFontScale(): number { return 1.0; }
}
// 平板策略
class TabletStrategy implements LayoutStrategy {
getColumns(): number { return 2; }
getGutter(): number { return 16; }
getPadding(): Padding { return { left: 24, right: 24 }; }
getNavPosition(): 'top' | 'bottom' | 'side' { return 'side'; }
getFontScale(): number { return 1.1; }
}
// PC策略
class PCStrategy implements LayoutStrategy {
getColumns(): number { return 3; }
getGutter(): number { return 24; }
getPadding(): Padding { return { left: 48, right: 48 }; }
getNavPosition(): 'top' | 'bottom' | 'side' { return 'top'; }
getFontScale(): number { return 1.0; }
}
// 车机策略
class CarStrategy implements LayoutStrategy {
getColumns(): number { return 1; }
getGutter(): number { return 12; }
getPadding(): Padding { return { left: 32, right: 32 }; }
getNavPosition(): 'top' | 'bottom' | 'side' { return 'side'; }
getFontScale(): number { return 1.3; } // 大字体
}
// 策略工厂
class LayoutStrategyFactory {
private static strategies: Map<string, LayoutStrategy> = new Map([
['phone', new PhoneStrategy()],
['tablet', new TabletStrategy()],
['2in1', new PCStrategy()],
['car', new CarStrategy()],
]);
static create(deviceType: string): LayoutStrategy {
return this.strategies.get(deviceType) || new PhoneStrategy();
}
}
// 上下文组件
@Component
export struct AdaptiveGrid {
@State private strategy: LayoutStrategy = LayoutStrategyFactory.create(deviceInfo.deviceType);
@Prop items: string[] = [];
build() {
GridRow({
columns: this.strategy.getColumns(),
gutter: { x: this.strategy.getGutter() }
}) {
ForEach(this.items, (item: string) => {
GridCol() {
Card({ title: item })
}
})
}
.padding(this.strategy.getPadding())
}
}
5.3 轻量级策略:表驱动编程
当策略逻辑较简单时,可使用 Record 替代完整的策略类,避免过度设计:
// 倒计时格式策略(轻量级实现)
const timeFormatStrategies: Record<string, (h: number, m: number, s: number, ms?: number) => string> = {
'hh:mm:ss': (h, m, s) => `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`,
'mm:ss': (_, m, s) => `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`,
'hh:mm:ss.ms': (h, m, s, ms) => `${String(h).padStart(2,'0')}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}.${String(ms).padStart(3,'0')}`,
};
function formatTime(format: string, hours: number, minutes: number, seconds: number, ms?: number): string {
const strategy = timeFormatStrategies[format] || timeFormatStrategies['hh:mm:ss'];
return strategy(hours, minutes, seconds, ms);
}
六、工厂模式:动态组件创建
6.1 模式核心思想
工厂模式(Factory Pattern)将对象的创建逻辑与使用逻辑分离。在 ArkUI 中,工厂模式常用于根据数据类型动态渲染不同的组件。
// 消息类型枚举
enum MessageType {
TEXT = 'text',
IMAGE = 'image',
VIDEO = 'video',
FILE = 'file',
VOICE = 'voice'
}
// 消息数据接口
interface MessageData {
id: string;
type: MessageType;
content: string;
sender: string;
timestamp: number;
}
// 组件工厂
class MessageComponentFactory {
private static builders: Map<MessageType, (data: MessageData) => void> = new Map();
static register(type: MessageType, builder: (data: MessageData) => void): void {
this.builders.set(type, builder);
}
static create(type: MessageType, data: MessageData): (() => void) | undefined {
return this.builders.get(type)?.bind(this, data);
}
}
// 注册具体组件
@Component
struct TextMessage {
@Prop data: MessageData;
build() {
Text(this.data.content)
.fontSize(14)
.padding(12)
.backgroundColor('#E3F2FD')
.borderRadius(8)
}
}
@Component
struct ImageMessage {
@Prop data: MessageData;
build() {
Image(this.data.content)
.width(200)
.height(150)
.objectFit(ImageFit.Cover)
.borderRadius(8)
}
}
// 在应用入口注册
MessageComponentFactory.register(MessageType.TEXT, (data: MessageData) => { TextMessage({ data }); });
MessageComponentFactory.register(MessageType.IMAGE, (data: MessageData) => { ImageMessage({ data }); });
// 使用工厂渲染消息列表
@Component
struct MessageList {
@Prop messages: MessageData[] = [];
build() {
List() {
ForEach(this.messages, (msg: MessageData) => {
ListItem() {
// 根据消息类型动态创建对应组件
if (msg.type === MessageType.TEXT) {
TextMessage({ data: msg })
} else if (msg.type === MessageType.IMAGE) {
ImageMessage({ data: msg })
}
}
})
}
}
}
七、单例模式:全局状态管理
7.1 模式核心思想
单例模式(Singleton Pattern)确保一个类只有一个实例,并提供一个全局访问点。在 ArkUI 中,单例常用于全局配置、用户会话和数据仓库。
// 全局配置中心
class AppConfig {
private static instance: AppConfig | null = null;
private constructor() {}
static getInstance(): AppConfig {
if (!AppConfig.instance) {
AppConfig.instance = new AppConfig();
}
return AppConfig.instance;
}
// 配置属性
apiBaseUrl: string = 'https://api.example.com';
requestTimeout: number = 30000;
maxRetryCount: number = 3;
enableDebugLog: boolean = false;
// 主题配置
themeMode: 'light' | 'dark' | 'system' = 'system';
fontScale: number = 1.0;
// 初始化方法
async initialize(): Promise<void> {
const pref = getContext().getApplicationContext().resourceManager;
// 从持久化存储加载配置
this.themeMode = AppStorage.get('theme_mode') || 'system';
this.fontScale = AppStorage.get('font_scale') || 1.0;
}
updateTheme(mode: 'light' | 'dark' | 'system'): void {
this.themeMode = mode;
AppStorage.setOrCreate('theme_mode', mode);
}
}
// 用户会话单例
class UserSession {
private static instance: UserSession | null = null;
private _token: string = '';
private _userId: string = '';
private _isLoggedIn: boolean = false;
private constructor() {}
static getInstance(): UserSession {
if (!UserSession.instance) {
UserSession.instance = new UserSession();
}
return UserSession.instance;
}
get token(): string { return this._token; }
get userId(): string { return this._userId; }
get isLoggedIn(): boolean { return this._isLoggedIn; }
login(token: string, userId: string): void {
this._token = token;
this._userId = userId;
this._isLoggedIn = true;
// 持久化
AppStorage.setOrCreate('auth_token', token);
}
logout(): void {
this._token = '';
this._userId = '';
this._isLoggedIn = false;
AppStorage.delete('auth_token');
}
}
八、装饰器模式:高阶组件与能力增强
8.1 模式核心思想
装饰器模式(Decorator Pattern)动态地给对象添加额外的职责。在 ArkUI 中,高阶组件(HOC)是装饰器模式的典型应用。
// 定义可装饰的组件接口
interface LoadingProps {
isLoading: boolean;
loadingText?: string;
}
// Loading 装饰器组件
@Component
export struct WithLoading {
@Prop isLoading: boolean = false;
@Prop loadingText: string = '加载中...';
@BuilderParam contentBuilder: () => void;
build() {
Stack() {
this.contentBuilder();
if (this.isLoading) {
Column() {
LoadingProgress()
.width(48)
.height(48)
.color('#007DFF')
Text(this.loadingText)
.fontSize(14)
.fontColor('#666666')
.margin({ top: 12 })
}
.width('100%')
.height('100%')
.backgroundColor('rgba(255,255,255,0.9)')
.justifyContent(FlexAlign.Center)
}
}
}
}
// 错误边界装饰器
@Component
export struct WithErrorBoundary {
@Prop hasError: boolean = false;
@Prop errorMessage?: string;
@BuilderParam contentBuilder: () => void;
@BuilderParam fallbackBuilder?: () => void;
@Builder
defaultFallback() {
Column({ space: 12 }) {
Image($r('app.media.ic_error'))
.width(64)
.height(64)
Text(this.errorMessage || '出错了,请稍后重试')
.fontSize(14)
.fontColor('#999999')
Button('重新加载')
.onClick(() => {
// 触发重试逻辑
})
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
}
build() {
if (this.hasError) {
if (this.fallbackBuilder) {
this.fallbackBuilder();
} else {
this.defaultFallback();
}
} else {
this.contentBuilder();
}
}
}
// 使用装饰器组合
@Entry
@Component
struct DataPage {
@State isLoading: boolean = true;
@State hasError: boolean = false;
@State data: string = '';
aboutToAppear() {
this.loadData();
}
async loadData() {
try {
this.isLoading = true;
this.hasError = false;
// 模拟异步请求
await new Promise(resolve => setTimeout(resolve, 1500));
this.data = '加载完成的数据';
} catch (e) {
this.hasError = true;
} finally {
this.isLoading = false;
}
}
@Builder
pageContent() {
Column() {
Text(this.data)
.fontSize(16)
.padding(24)
}
}
build() {
WithErrorBoundary({
hasError: this.hasError,
contentBuilder: () => {
WithLoading({
isLoading: this.isLoading,
contentBuilder: this.pageContent
})
}
})
}
}
九、命令模式:撤销重做与操作队列
9.1 模式核心思想
命令模式(Command Pattern)将请求封装为对象,从而可以用不同的请求、队列或日志来参数化其他对象,同时支持可撤销的操作。
// 命令接口
interface Command {
execute(): void;
undo(): void;
getDescription(): string;
}
// 具体命令:文本编辑
class TextEditCommand implements Command {
private oldText: string;
private newText: string;
private target: { text: string };
constructor(target: { text: string }, newText: string) {
this.target = target;
this.oldText = target.text;
this.newText = newText;
}
execute(): void {
this.target.text = this.newText;
}
undo(): void {
this.target.text = this.oldText;
}
getDescription(): string {
return `文本编辑: "${this.oldText}" → "${this.newText}"`;
}
}
// 命令管理器(支持撤销重做)
class CommandManager {
private history: Command[] = [];
private currentIndex: number = -1;
private maxHistory: number = 50;
execute(command: Command): void {
// 清除当前位置之后的历史
if (this.currentIndex < this.history.length - 1) {
this.history = this.history.slice(0, this.currentIndex + 1);
}
command.execute();
this.history.push(command);
this.currentIndex++;
// 限制历史记录长度
if (this.history.length > this.maxHistory) {
this.history.shift();
this.currentIndex--;
}
}
undo(): boolean {
if (this.currentIndex < 0) return false;
this.history[this.currentIndex].undo();
this.currentIndex--;
return true;
}
redo(): boolean {
if (this.currentIndex >= this.history.length - 1) return false;
this.currentIndex++;
this.history[this.currentIndex].execute();
return true;
}
canUndo(): boolean {
return this.currentIndex >= 0;
}
canRedo(): boolean {
return this.currentIndex < this.history.length - 1;
}
}
// 在组件中使用
@Component
struct TextEditor {
@State text: string = '';
private commandManager = new CommandManager();
private updateText(newText: string) {
const command = new TextEditCommand({ text: this.text }, newText);
this.commandManager.execute(command);
this.text = newText; // 触发UI更新
}
build() {
Column() {
TextInput({ text: this.text })
.onChange((value) => {
this.updateText(value);
})
Row({ space: 16 }) {
Button('撤销')
.enabled(this.commandManager.canUndo())
.onClick(() => {
this.commandManager.undo();
// 需要重新获取状态
})
Button('重做')
.enabled(this.commandManager.canRedo())
.onClick(() => {
this.commandManager.redo();
})
}
}
}
}
十、模式融合:多模式协同实战
在实际项目中,单一设计模式往往难以满足复杂需求。以下是一个融合多种模式的综合案例——任务管理应用。
// 1. Builder 模式:任务对象构造
@Observed
class Task {
id: string;
title: string;
priority: 'low' | 'medium' | 'high';
status: 'pending' | 'completed';
createdAt: number;
private constructor(builder: TaskBuilder) {
this.id = builder.id;
this.title = builder.title;
this.priority = builder.priority;
this.status = builder.status;
this.createdAt = builder.createdAt;
}
static builder(): TaskBuilder {
return new TaskBuilder();
}
}
class TaskBuilder {
id: string = Date.now().toString();
title: string = '';
priority: 'low' | 'medium' | 'high' = 'medium';
status: 'pending' | 'completed' = 'pending';
createdAt: number = Date.now();
setTitle(title: string): TaskBuilder { this.title = title; return this; }
setPriority(p: 'low' | 'medium' | 'high'): TaskBuilder { this.priority = p; return this; }
setStatus(s: 'pending' | 'completed'): TaskBuilder { this.status = s; return this; }
build(): Task { return new Task(this); }
}
// 2. 单例模式:任务仓库
class TaskRepository {
private static instance: TaskRepository | null = null;
@Observed tasks: Task[] = [];
private eventHub = EventHub.getInstance();
private constructor() {}
static getInstance(): TaskRepository {
if (!TaskRepository.instance) {
TaskRepository.instance = new TaskRepository();
}
return TaskRepository.instance;
}
addTask(task: Task): void {
this.tasks.push(task);
this.eventHub.emit('task:added', task);
}
completeTask(id: string): void {
const task = this.tasks.find(t => t.id === id);
if (task) {
task.status = 'completed';
this.eventHub.emit('task:updated', task);
}
}
}
// 3. 策略模式:任务排序策略
interface SortStrategy {
sort(tasks: Task[]): Task[];
}
class PrioritySortStrategy implements SortStrategy {
sort(tasks: Task[]): Task[] {
const priorityMap = { high: 3, medium: 2, low: 1 };
return [...tasks].sort((a, b) => priorityMap[b.priority] - priorityMap[a.priority]);
}
}
class TimeSortStrategy implements SortStrategy {
sort(tasks: Task[]): Task[] {
return [...tasks].sort((a, b) => b.createdAt - a.createdAt);
}
}
// 4. 组合模式:任务卡片组件
@Component
struct TaskCard {
@ObjectLink task: Task;
@BuilderParam actionBuilder?: () => void;
build() {
Row() {
Column({ space: 4 }) {
Text(this.task.title)
.fontSize(16)
.fontWeight(FontWeight.Medium)
.decoration(this.task.status === 'completed' ? TextDecorationType.LineThrough : TextDecorationType.None)
Text(this.task.priority)
.fontSize(12)
.fontColor(this.task.priority === 'high' ? '#F5222D' : this.task.priority === 'medium' ? '#FAAD14' : '#52C41A')
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
if (this.actionBuilder) {
this.actionBuilder();
}
}
.width('100%')
.padding(16)
.backgroundColor(this.task.status === 'completed' ? '#F6FFED' : '#FFFFFF')
.borderRadius(8)
}
}
// 5. 观察者模式:任务列表自动刷新
@Component
struct TaskListPage {
@State private repository = TaskRepository.getInstance();
@State private sortStrategy: SortStrategy = new TimeSortStrategy();
private eventHub = EventHub.getInstance();
private unsubscribe?: () => void;
aboutToAppear() {
this.unsubscribe = this.eventHub.on('task:added', () => {
// 触发重渲染
this.repository = TaskRepository.getInstance();
});
}
aboutToDisappear() {
this.unsubscribe?.();
}
private getSortedTasks(): Task[] {
return this.sortStrategy.sort(this.repository.tasks);
}
build() {
Column() {
Row({ space: 12 }) {
Button('按优先级')
.onClick(() => { this.sortStrategy = new PrioritySortStrategy(); })
Button('按时间')
.onClick(() => { this.sortStrategy = new TimeSortStrategy(); })
}
.padding(16)
List() {
ForEach(this.getSortedTasks(), (task: Task) => {
ListItem() {
TaskCard({
task: task,
actionBuilder: () => {
Button('完成')
.enabled(task.status === 'pending')
.onClick(() => this.repository.completeTask(task.id))
}
})
}
})
}
}
}
}
十一、设计模式使用原则
11.1 何时使用设计模式
| 场景特征 | 推荐模式 | 反例警示 |
|---|---|---|
| 对象构造参数超过5个且多为可选 | Builder 模式 | 构造函数参数过长 |
| 需要全局唯一实例 | 单例模式 | 多个实例导致状态不一致 |
| 运行时切换算法/布局 | 策略模式 | 大量 if-else 分支 |
| 一对多状态通知 | 观察者模式 | 层层回调传递 |
| 动态创建不同类型组件 | 工厂模式 | 组件内直接 switch-case |
| 给组件添加通用能力 | 装饰器模式 | 每个组件重复实现 loading/error |
11.2 避免过度设计
设计模式是工具而非目的。以下情况不应强行使用设计模式:
- 简单场景:只有两个策略且逻辑简单,直接用
if-else更清晰 - 过早抽象:需求尚未稳定时,不要为"可能的扩展"引入复杂模式
- 代码量激增:引入模式后代码量增加超过50%,需重新评估收益
- 团队认知成本:模式过于晦涩导致团队成员理解困难
11.3 模式选型检查表
- 当前问题是否确实需要引入设计模式解决?
- 引入后代码量变化是否在可接受范围内?
- 团队成员是否理解该模式的核心思想?
- 是否有更简单的替代方案(如表驱动编程)?
- 模式引入后是否提升了可测试性?
十二、总结
HarmonyOS ArkUI 的声明式框架为设计模式的应用提供了独特的土壤:@BuilderParam 天然支持组合模式,@State/@Observed 实现了框架级观察者模式,@Component 的组件化思想与装饰器模式高度契合。开发者需要做的不是生搬硬套 GoF 的 23 种模式,而是理解每种模式要解决的核心问题,并结合 ArkTS 的语言特性进行本土化改造。
本文介绍的六种核心模式——组合、观察者、策略、工厂、单例、装饰器——覆盖了 ArkUI 开发中 80% 的架构设计场景。掌握它们的正确用法,并在适当的时机进行模式融合,是构建可维护、可扩展 HarmonyOS 应用的关键能力。
转载自:https://blog.csdn.net/u014727709/article/details/163572677
欢迎 👍点赞✍评论⭐收藏,欢迎指正
更多推荐


所有评论(0)