大佬,我还是喜欢简单的东西,但楼主分享的东西确实能学到东西,,
如果是为了少new的话 欢迎大家品尝
declare global {
interface Function {
/**
* 该方法请注意,只属于拥有Ins的静态方法对象才能调用
* 搭配@SingleFunc 一起使用
* 传入类型参数,当成返回的类型
*/
Ins<T>(arg: { new(...args): T }): T
}
}
/**
* 单利1 装饰器模式 对继承无影响
* @param target
* @returns
*/
export function SingleFunc(target: any) {
target.Ins = function () {
if (!target.__ins__) {
target.__ins__ = new target()
}
return target.__ins__
}
return target
}
/**
* 单利 2
* 继承的方式
*/
export class SingleClass {
private static _ins: any = null
static Ins<T>(target: { new(): T }): T {
if (!this._ins) {
this._ins = new target()
}
return this._ins as T
}
}
楼主对于new来new去不方便的ioc理解也是错的
ioc是处理对象依赖的,以及按照接口编程,随时替换实现
确实,ioc主要是处理对象依赖,,
我举个例子
/**
* 日志管理器
* 提供日志的细化分类和颜色区分功能。
*/
class LogMgr {
private static _instance: LogMgr; // 单例实例
private _isEnabled: boolean = true; // 日志开关,默认开启
private static LogType = {
Debug: 1,
Info: 2,
Warn: 3,
Err: 4,
}; // 日志类型
// 日志类型对应的颜色和前缀文本
private _logConfig: { [key in number]: { color: string; prefix: string } } = {
[LogMgr.LogType.Debug]: { color: 'color: #1E90FF; background-color: #E6F4FF;', prefix: '【调试】' }, // 淡蓝色背景与深蓝色文字
[LogMgr.LogType.Info]: { color: 'color: #CDA434; background-color: #FFFBE6;', prefix: '【信息】' }, // 淡黄色背景与金色文字
[LogMgr.LogType.Warn]: { color: 'color: #FFA500; background-color: #FFF5E6;', prefix: '【警告】' }, // 淡橙色背景与橙色文字
[LogMgr.LogType.Err]: { color: 'color: #FF4500; background-color: #FFE6E6;', prefix: '【错误】' }, // 淡红色背景与暗红色文字
};
// 私有构造函数,确保外部无法直接通过new创建实例
private constructor(enabled: boolean = true) {
this._isEnabled = enabled;
}
// 获取单例实例
public static get instance(): LogMgr {
if (!this._instance) {
this._instance = new LogMgr();
}
return this._instance;
}
/**
* 设置日志输出是否启用。
* @param enabled 是否启用日志输出。
*/
public setEnabled(enabled: boolean): void {
this._isEnabled = enabled;
}
/**
* 根据日志类型输出日志信息,附带可选的数据。
* @param logType 日志类型。
* @param message 日志信息。
* @param data 可选的数据。
*/
private logMessage(logType: number, message: string, data?: any): void {
if (!this._isEnabled) return;
const { color, prefix } = this._logConfig[logType];
if (data !== undefined) {
console.log(`%c${prefix} ${message}`, color, data);
} else {
console.log(`%c${prefix} ${message}`, color);
}
}
// 具体日志方法,附带可选的数据参数
public debug(message: string, data?: any): void { this.logMessage(LogMgr.LogType.Debug, message, data); }
public info(message: string, data?: any): void { this.logMessage(LogMgr.LogType.Info, message, data); }
public warn(message: string, data?: any): void { this.logMessage(LogMgr.LogType.Warn, message, data); }
public err(message: string, data?: any): void { this.logMessage(LogMgr.LogType.Err, message, data); }
}
// 导出LogMgr的单例实例
export const logMgr = LogMgr.instance;
接下来放到App.ts里:
import { logMgr } from "./manager/LogMgr";
/** 框架核心模块访问入口 */
class App {
static log = logMgr; // 日志管理器
};
// 导出App全局名称为app
export const app = App;
最后其他地方
import { app } from '../../../core/scripts/App';
app.log.debug('日志内容);
再给你优化下
class App {
static get log() {
return logMgr
}
};
declare global {
interface Window {
app: App
}
var app: App
}
window.app = new App()
你可以到处app.log了 不用去import了
确实,当时就是不太懂。
这个跟你的想法并不相同哦。
哎呀哥,我老早就想这样搞了,就是不知道怎么设置全局变量,现在知道了
// 全局声明
declare global {
interface Window {
app1: App1;
}
var app1: App1;
}
// App1 类定义
class App1 {
// 返回 LogMgr 类型的 log 属性
get log(): LogMgr {
return logMgr;
}
}
// 将 App1 的实例赋值给全局变量 app1
window.app1 = new App1();
// 现在你可以在全局范围内使用 app1.log
app1.log.debug("Hello, world!");
而且这样还是能在IDE里显示被调用函数的注释,能ctrl
+左键跟踪到函数
declare global {
interface Global{
}
}
Window换成Global 就可以不用挂到window上 直接全局变量赋值了 不过这样就全局变量污染了还是有问题的
所以这种东西不能多干 一个就够了 最好名字还特别点
我也用SpringBoot、Cocos Creator开发过各种项目,说下我个人的理解。
Ioc容器是在项目初始化的时候把所有的bean初始化,放入容器中,然后反向注入到各个成员变量来使用。这种方式在启动的时候会把所有的单例都初始化,所以spring项目启动的时候会比较慢。但是优点是:
1.在实际调用的时候,bean已经初始化完成,所以实际调用执行会快一些。
2.避免单例被重复new出来。我们一般获取单例都是XXX.getIns()来获取,getIns中如果对象不存在会new出来,存在就直接使用已经new好的。但是在并发执行的时候,很容易会重复new,所以干脆在启动的时候全部new好,避免重复new。
但是这些优点在游戏前端开发中并不明显。一开始就把全部bean初始化,那意味着内存占用会很高,这对前端开发不友好。比如我们进入战斗场景,一般都是进入战斗才把战斗需要的类实例化,战斗结束就把类全部释放(同时还有资源释放),可以减少内存占用和耗电。而spring的这种设计模式就不适合做这种事。后端开发适用这种方式,是因为后端的服务器内存一般比较大,不需要考虑内存占用问题,并且一般后端的单例都是不需要释放的,启动new了之后,到关服都不需要手动释放实例。
如果从方便的角度说,我觉得XXX.getIns()来获取单例更方便,不用像Spring那样每次都去先定义成员变量才能拿单例。因为前端没有并发问题,XXX.getIns()不会出现重复new的现象。而后端开发有并发问题,XXX.getIns()不加锁就可能重复new,加锁又影响性能,所以后端才会采用统一从ioc容器获取bean。
解释最全 
了解了~ 
我是核心框架单例,提前new
具体到游戏的时候,才手动new
看你框架代码风格很适合我口味,撒时候多弄些工具组件出来啊,按我的说法,直接按36元买断可行?
不要加什么授权就行
大家最能接受的也是买断,所以只能买断制了,如果我没上班会花时间做,上班的话就不确定,明天要去面试了