cocos單例工廠和自動裝配

cocos單例工廠和自動裝配

1 單例工廠

1.1 分析
  1. 實例字典

原理很簡單,只是一個map,確保每個類只保留一個實例;

private static _instances = new Map<string, any>();
  1. 獲取與存儲實例

這邊使用的方式是生成一個唯一的id存儲在類上,獲取實例的時候通過這個id值拿到實例對象;

這里很多人會疑惑,為什么不直接使用類名作為標識來記錄和獲取實例?原因很簡單,在項目構建之后類名是隨機的、可能重復的;如果還是希望使用類名作為標識,可以參考cocos 3.x@ccclass裝飾器的寫法,將類名字符串傳入。(ccclass源碼)

因設計過程中考慮到可能存在需傳參的構造器,所以為了強化職責性就不考慮傳入類名作為標識了;

public static getInst<T>(classType: { new(...args): T }): T {let key = classType['_singletonId'];if (!key || !this._instances[key]) {console.error("無實例");return null;}return this._instances[key];
}
public static setInst(classType, ...args): void {if(classType._singletonId)return;let key = UUID.generate();while(this._instances[key]) {key = UUID.generate();}this._instances[key] = new classType(...args);classType._singletonId = key;
}
  1. 單例注解(裝飾器)

使用方式在需要托管的類上直接添加Singleton即可,如果規范是所有單例都無參可以將返回的函數上移(代碼段中可見),標記單例時寫法更簡潔;

checkIsClass函數用于檢測標記的是否為類;

export function Singleton(...args) {return function (target: any) {if (checkIsClass(target)){SingletonFactory.setInst(target, ...args);}}
}
const checkIsClass = function (target: unknown): boolean {return (typeof target === "function" && "prototype" in target && target.prototype.constructor === target);
}
//規范是單例都無參的寫法
export function Singleton(target: any) {if (checkIsClass(target)){SingletonFactory.setInst(target, ...args);}
}
//使用方式有參
@Singleton(info)
export default class DataCenter{private info = null;constructor(info) {this.info = info;}
}
//使用方式無參
@Singleton()
export default class EventManager{}
  1. 自動注入

自動注入也是使用的注解方式,標記主動注入的屬性所屬的類一定要使用單例注解,否則取值為空;

需要注意的是,因為注解的執行時機在創建階段,而循環依賴的類在使用import時不能立即獲得類,故傳入的target會出現未定義的狀況,故希望使用自動注入的注解時一定要避免循環依賴的出現。存在循環依賴的類只能在使用時通過單例工廠取獲取實例;

export function Autowired<T>(constructor: new (...args) => T) {return function (target: any, propertyName) {Object.defineProperty(target, propertyName, {configurable: true,get: function () {return SingletonFactory.getInst(constructor);},set: function(value) {}})}
}
//Autowired使用方式
export default class xxxView {@Autowired(LobbyLogic)lobbyLogic: LobbyLogic = null;
}
//直接使用單例工廠
SingletonFactory.getInst(單例類);
1.3 源碼
  1. 單例工廠實現
import UUID from "./UUID";
export default class SingletonFactory {private static _instances = new Map<string, any>();public static getInst<T>(classType: { new(...args): T }): T {let key = classType['_singletonId'];if (!key || !this._instances[key]){console.error("無實例");return null;}return this._instances[key];}static setInst(classType, ...args): void {if(classType._singletonId)return;let key = UUID.generate();while (this._instances[key]) {key = UUID.generate();}this._instances[key] = new classType(...args);classType._singletonId = key;}
}
export function Singleton(...args) {return function (target: any) {if (checkIsClass(target)){SingletonFactory.setInst(target, ...args);}}
}
export function Autowired<T>(constructor: new (...args) => T) {return function (target: any, propertyName) {Object.defineProperty(target, propertyName, {configurable: true,get: function () {return SingletonFactory.getInst(constructor);},set: function(value) {}})}
}
const checkIsClass = function (target: unknown): boolean {return (typeof target === "function" && "prototype" in target && target.prototype.constructor === target);
}
  1. UUID實現
export default class UUID {static generate(): string {const hexDigits = '0123456789abcdef'const s: string[] = Array(36).fill('')for (let i = 0; i < 36; i++) {s[i] = hexDigits.charAt(Math.floor(Math.random() * 0x10))}s[14] = '4's[19] = hexDigits.charAt((parseInt(s[19], 16) & 0x3) | 0x8)s[8] = s[13] = s[18] = s[23] = '-'return s.join('');}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85824.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85824.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85824.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

django paramiko 跳轉登錄

在使用Django框架結合Paramiko進行SSH遠程操作時&#xff0c;通常涉及到自動化腳本的執行&#xff0c;比如遠程服務器上的命令執行、文件傳輸等。如果你的需求是“跳轉登錄”&#xff0c;即在登錄遠程服務器后&#xff0c;再通過該服務器的SSH連接跳轉到另一臺服務器&#xff0…

《C++初階之類和對象》【命名空間 + 輸入輸出 + 缺省參數 + 函數重載】

【命名空間 輸入&輸出 缺省參數 函數重載】目錄 前言&#xff1a;---------------hello world---------------比較C語言和C的第一個程序&#xff1a;hello word ---------------命名空間---------------什么是命名空間&#xff1f;怎么使用命名空間&#xff1f;怎么定義…

[USACO1.5] 八皇后 Checker Challenge Java

import java.util.*;public class Main {// 標記 對角線1&#xff0c;對角線2&#xff0c;所在x軸 是否存在棋子static boolean[] d1 new boolean[100], d2 new boolean[100], d new boolean[100]; static int n, ans 0;static int[] arr new int[14]; // 記錄一輪棋子位置…

云服務器Xshell登錄拒絕訪問排查

根據你的描述&#xff0c;使用Xshell 8登錄云服務器時顯示“拒絕訪問”&#xff0c;可能涉及多個原因。以下結合搜索結果整理出排查和解決方法&#xff0c;按優先級排序&#xff1a; 一、檢查基礎網絡與端口連通性 本地網絡與服務器IP是否可達 在本地電腦的CMD中執行 ping 服務…

Python爬蟲實戰:研究urlunparse函數相關技術

1. 引言 1.1 研究背景與意義 在當今信息爆炸的時代,互聯網上的數據量呈現出指數級增長。如何從海量的網頁數據中高效地獲取有價值的信息,成為了學術界和工業界共同關注的問題。網絡爬蟲作為一種自動獲取網頁內容的技術,能夠按照預定的規則遍歷互聯網上的網頁,并提取出所需…

Spring AI學習一

隨著Chatpt的火爆&#xff0c;現在Spring官方也開始支持AI了并推出了Spring AI框架&#xff0c;目前還沒發布正式版本&#xff0c;這里可以先看一下官方依賴的版本。 Spring官網地址可以看這里&#xff1a;Spring | Home 目前官網上是有這兩個版本&#xff1a;1.0.0和1.1.0-SN…

reverse筆記

一&#xff0c;strcat的使用方法&#xff08;在攻防世界中刷題時遇到的&#xff09; 二&#xff0c;殼&#xff08;做題遇到過但是一直不是很理解&#xff0c;今天查了一下&#xff09; 殼是一種軟件保護技術&#xff0c;能夠防止程序被輕易地分析和修改。 總而言之&#xff0…

spring4第7-8課-AOP的5種通知類型+切點定義詳解+執行順序

繼續學習&#xff0c;方便自己復查記錄 ①AOP簡介&#xff1a; 面向切面編程(也叫面向方面編程)&#xff1a;Aspect Oriented Programming(AOP)。 Spring框架中的一個重要內容。。 通過預編譯方式和運行期間動態代理實現在不修改源代碼的情況下給程序動態統一添加功能…

EscapeX:去中心化游戲,開啟極限娛樂新體驗

VEX 平臺推出全新去中心化游戲 EscapeX&#xff08;數字逃脫&#xff09;&#xff0c;創新性地將大逃殺玩法與區塊鏈技術相融合。用戶不僅能暢享緊張刺激的解謎過程&#xff0c;更能在去中心化、公正透明的環境中參與游戲。EscapeX 的上線&#xff0c;為 VEX 生態注入全新活力&…

Multi Agents Collaboration OS:Web DeepSearch System

背景&#xff1a;多智能體協作驅動網絡信息處理的范式革新 隨著大型語言模型&#xff08;LLM&#xff09;能力的突破性進展&#xff0c;人工智能正從“單點賦能”向“系統協同”演進。傳統單一智能體在復雜業務場景中逐漸顯露局限&#xff1a;面對需多維度知識整合、動態任務拆…

React 第五十三節 Router中 useRouteError 的使用詳解和案例分析

前言 useRouteError 是 React Router v6.4 引入的關鍵錯誤處理鉤子&#xff0c;用于在 路由錯誤邊界&#xff08;Error Boundary&#xff09; 中獲取路由操作過程中發生的錯誤信息。 它提供了優雅的錯誤處理機制&#xff0c;讓開發者能夠創建用戶友好的錯誤界面。 一、useRou…

[arthas]arthas安裝使用

arthas是阿里開源的一個java線上監控以及診斷工具&#xff0c;在docker容器中我們無需重啟服務&#xff0c;也不用更改代碼&#xff0c;就可以完成對應用內存、線程、日志級別的修改、方法調用的出入參、異常監測、執行耗時等&#xff0c;xxxx.xxxx.xxxxx為脫敏內容 1. 在docke…

Flask-Babel 使用示例

下面創建一個簡單的 Flask-Babel 示例&#xff0c;展示如何在 Flask 應用中實現國際化和本地化功能。這個示例將包括多語言支持&#xff08;中文和英文&#xff09;、語言切換功能以及翻譯文本的使用。 項目結構 我們將創建以下文件結構&#xff1a; 1. 首先&#xff0c;創…

[論文閱讀] 軟件工程 | 量子計算如何賦能軟件工程(Quantum-Based Software Engineering)

arXiv:2505.23674 [pdf, html, other] Quantum-Based Software Engineering Jianjun Zhao Subjects: Software Engineering (cs.SE); Quantum Physics (quant-ph) 量子計算如何賦能軟件工程 我們在開發軟件時&#xff0c;常常會遇到一些棘手的問題。比如&#xff0c;為了確保軟…

Ansible 進階 - Roles 與 Inventory 的高效組織

Ansible 進階 - Roles 與 Inventory 的高效組織 如果說 Playbook 是一份完整的“菜譜”,那么 Role (角色) 就可以被看作是制作這道菜(或一桌菜)所需的標準化“備料包”或“半成品組件”。例如,我們可以有一個“Nginx Web 服務器安裝配置 Role”、“MySQL 數據庫基礎設置 Ro…

青少年編程與數學 01-011 系統軟件簡介 04 Linux操作系統

青少年編程與數學 01-011 系統軟件簡介 04 Linux操作系統 一、Linux 的發展歷程&#xff08;一&#xff09;起源&#xff08;二&#xff09;早期發展&#xff08;三&#xff09;成熟與普及&#xff08;四&#xff09;移動與嵌入式領域的拓展 二、Linux 的內核與架構&#xff08…

將圖形可視化工具的 Python 腳本打包為 Windows 應用程序

前文我們已經寫了一個基于python的tkinter庫和matplotlib庫的圖形可視化工具。 基于Python的tkinter庫的圖形可視化工具&#xff08;15種圖形的完整代碼&#xff09;:基于Python的tkinter庫的圖形可視化工具&#xff08;15種圖形的完整代碼&#xff09;-CSDN博客 在前文基礎上&…

【Kotlin】簡介變量類接口

【Kotlin】簡介&變量&類&接口 【Kotlin】數字&字符串&數組&集合 【Kotlin】高階函數&Lambda&內聯函數 【Kotlin】表達式&關鍵字 文章目錄 Kotlin_簡介&變量&類&接口Kotlin的特性Kotlin優勢創建Kotlin項目變量變量保存了指向對…

OpenCV種的cv::Mat與Qt種的QImage類型相互轉換

一、首先了解cv::Mat結構體 cv::Mat::step與QImage轉換有著較大的關系。 step的幾個類別區分: step:矩陣第一行元素的字節數step[0]:矩陣第一行元素的字節數step[1]:矩陣中一個元素的字節數step1(0):矩陣中一行有幾個通道數step1(1):一個元素有幾個通道數(channel()) cv::Ma…

搭建基于VsCode的ESP32的開發環境教程

一、VsCode搜索ESP-IDF插件 根據插件處搜索找到ESP-IDF并安裝 安裝完成 二、配置安裝ESP-IDF 配置IDF 按照如下配置&#xff0c;點擊安裝 安裝完成 三、使用案例程序 創建一個閃光燈的例子程序&#xff0c;演示程序編譯下載。 選擇blink例子&#xff0c;閃爍LED的程序 選…