1、模式標準
模式名稱:迭代器模式
模式分類:行為型
模式意圖:提供一種方法順序訪問一個聚合對象中的各個元素,且不需要暴露該對象的內部表示.
結構圖:
?
適用于:
? ? 1、當你需要遍歷一個復雜的數據結構,如樹或圖,而不想公開其內部表示時。
? ? 2、當你有一個集合對象,需要提供多種遍歷方式,或者需要自定義遍歷方式時。
? ? 3、當你需要讓代碼獨立于特定的類或接口,使代碼能夠與多種數據類型一起工作時。
主要成員:
-
迭代器接口(Iterator):定義遍歷元素所需的方法,例如?
next()
,hasNext()
?等。 -
具體迭代器(Concrete Iterator):實現迭代器接口,并跟蹤遍歷的當前位置。
-
聚合接口(Aggregate):定義創建相應迭代器對象的接口。
-
具體聚合(Concrete Aggregate):實現聚合接口,返回具體迭代器的實例。
?2、分析與設計??
在游戲中會經常用到迭代器,一般情況下我們定義一個index,隨著游戲或者操作進行index++,來進行下一步對象或者操作。這里我們用到的場景是新手指引,當某個事件發生時,新手指引聚合器創建一個指引迭代器,指引迭代器指引玩家一步一步的按順序完成。
意圖:提供一種方法順序訪問一個聚合對象(新手指引聚合器)中的各個元素(新手指引),且不需要暴露該對象的內部表示
3、開始打造
?
// 聚合接口
export interface IAggregate {createIterator(): IIterator
}
// 具體的新手指引聚合
export class GuideAggregate implements IAggregate {steps: GuideStep[] = []addStep(step: GuideStep) {this.steps.push(step)}createIterator() {return new GuideIterator(this.steps)}
}
// 迭代器接口
export interface IIterator {hasNext(): booleannext(): any
}
// 具體的新手指引迭代器
export class GuideIterator implements IIterator {private index: number = 0steps: GuideStep[] = []constructor(steps: GuideStep[]) {this.steps = steps}hasNext(): boolean {return this.index < this.steps.length;}next(): GuideStep | null {if (this.hasNext()) {return this.steps[this.index++];} else {return null;}}
}
// 指引步驟
export class GuideStep {private onClickResolver: (() => void) | null = null;guideItem: IGuideItemconstructor(_item: IGuideItem) {this.guideItem = _item}execute() {const targetNode = find(this.guideItem.targetNodePath)// 注冊事件監聽器targetNode.on(Node.EventType.TOUCH_START, this.handleClick)return targetNode // 外面要用到先返回}// 當用戶點擊時,解決 Promiseprivate handleClick = () => {const targetNode = find(this.guideItem.targetNodePath)targetNode.off(Node.EventType.TOUCH_START, this.handleClick)if (this.onClickResolver) {this.onClickResolver();}}// 返回一個 Promise,該 Promise 在用戶點擊后被resolveonClick(): Promise<void> {console.log('等待點擊')return new Promise((resolve) => {this.onClickResolver = resolve;});}
}
4、開始使用
let guides: IGuideItem[] = [{"group": "battle_start","targetNodePath": "root/UICanvas/battle_index/help_move_up","text": "點擊的虛框","text_size": [200, 200],"text_pos_index": 3}, {"group": "battle_start","targetNodePath": "root/UICanvas/battle_index/help_move_up","text": "點擊的虛框","text_size": [200, 200],"text_pos_index": 3}]// 開始本次的新手指引let guideAggregate = new GuideAggregate();guides.forEach((_item) => {guideAggregate.addStep(new GuideStep(_item));})async function runGuide(guide: GuideAggregate) {// 創建新手指引的指引層PlayerGuideSystem.createGuideNodes(comp)let iterator = guide.createIterator();while (iterator.hasNext()) {console.log('準備指引')let step = iterator.next();if (step !== null) {step.execute();await step.onClick(); // 等待用戶點擊console.log('點擊完成')}}// 清理新手指引的指引層PlayerGuideSystem.clearNodes()console.log('指導層清理完成')}runGuide(guideAggregate);
完工