公用对象池

什么是对象池?

对象池顾名思义就是存放对象的池子,主要是为了重复利用对象。将不用的对象扔进池子里,需要用的时候再从池子中取出来。这样的一套机制我们称为对象池。

为什么用对象池?

其实从定义我们就可以看出来,说白了就是为了提高资源的复用性。减少频繁的创建和销毁。对程序而言,频繁的创建和销毁就意味着频繁地分配内存和释放内存,这种情况会引起内存抖动、内存碎片、增加GC的负担和触发频率等一些列的性能问题。

对象池的应用场景?

主要作用于频繁创建和销毁的对象,例如子弹

对象池实现

从定义来看,很显然每一种需要频繁创建和销毁的物体都需要实现一套自己对象池,因为在一个对象池中回收和取出的一定是相同的对象,那开发过程中我们可能会遇到很多种不同类型的对象,他们都需要重复利用,那么怎么能实现简单好用的对象池呢?有没有一种方法或模板可以实现所有类型对象的对象池呢?
有经验的开发到这里肯定会想到把对象池的对象给抽象,那么我们可以有一套抽象的对象池来管理抽象的对象,在使用的时候在把对象池和对象进行具象化。就像这样:

public abstract class IPool<T>{}

那下面是不是要想一下,这个抽象的对象池内部需要一些什么样的属性和方法?
首先我们肯定要给这个对象池定一个容量,还要有一个属性来表示当前的存储数量,我们肯定也要定义一个容器来存这些对象,根据对象池的特性我们可以用Queue或者Stack,那这里我选择了Queue。我们还需要一些抽象方法,来创建、回收、销毁对象,也许我们在从对象池中取对象时还需要一些初始化的操作,初始化时也许我们还要接收一些参数,那么这个操作也要抽象成方法。
那大致就是这样:

public abstract class IPool<T>{/// <summary>/// 对象池最大容量/// </summary>public int MaxCount = 20;/// <summary>/// 对象池当前存储数量/// </summary>public int Count => poolQueue == null ? 0 : poolQueue.Count;/// <summary>/// 回收队列/// </summary>private Queue<T> poolQueue = new Queue<T>();/// <summary>/// 创建对象/// </summary>/// <returns></returns>protected abstract T OnCreateItem();/// <summary>/// 获取对象之前(一般用来初始化对象数据)/// </summary>/// <param name="item">对象</param>/// <param name="userData">用户定义数据</param>protected abstract void OnGetBefore(T item, object userData);/// <summary>/// 回收对象时触发/// </summary>/// <param name="item">目标对象</param>/// <returns>是否可以回收</returns>protected abstract bool OnRecycle(T item);/// <summary>/// 销毁对象时触发/// </summary>/// <param name="item">目标对象</param>protected abstract void OnDestroyItem(T item);
}

上面我们基本上就把该抽象的方法都给抽象了,那我们也不能仅仅只是抽象吧好像什么实事也没做,那下面就要写一些看得见摸得着的实际的东西了。
最重要的我们需要取对象和回收对象,回收对象我们可能一次回收一个,也可能一次回收多个,可能这个回收的对象需要重复利用也可能直接舍弃销毁,我们还可能预加载一些对象为了在下一次使用时能快速的拿到
那完整的对象池如下方:

    /// <summary>/// 对象池/// </summary>/// <typeparam name="T">池对象泛型</typeparam>public abstract class IPool<T>{/// <summary>/// 对象池最大容量/// </summary>public int MaxCount = 20;/// <summary>/// 对象池当前存储数量/// </summary>public int Count => poolQueue == null ? 0 : poolQueue.Count;/// <summary>/// 回收队列/// </summary>private Queue<T> poolQueue = new Queue<T>();/// <summary>/// 预加载/// </summary>/// <param name="count">预加载数量</param>public void PreLoad(int count){count = Mathf.Min(count, MaxCount);if (Count >= count) return;T item;for (int i = Count; i < count; i++){item = OnCreateItem();Recycle(item);}}/// <summary>/// 取一个对象/// </summary>/// <param name="userData">用户定义数据</param>/// <returns></returns>public T Get(object userData=null){T t;if (Count == 0){t = OnCreateItem();}else{t = poolQueue.Dequeue();if (t == null) t = Get(userData);}OnGetBefore(t,userData);return t;}/// <summary>/// 回收对象/// </summary>/// <param name="item">目标对象</param>/// <param name="isDestroy">是否销毁</param>public void Recycle(T item,bool isDestroy=false){if (Count >= MaxCount) isDestroy = true;if (isDestroy){OnDestroyItem(item);}else{if (OnRecycle(item)){poolQueue.Enqueue(item);}else OnDestroyItem(item);}}/// <summary>/// 回收多个对象/// </summary>/// <param name="items">对象列表</param>/// <param name="isDestroy">是否彻底销毁</param>public void Recycles(IList<T> items,bool isDestroy=false){int count = items == null ? 0 : items.Count;if (count == 0) return;for (int i = 0; i < count; i++){Recycle(items[i],isDestroy);}}/// <summary>/// 创建对象/// </summary>/// <returns></returns>protected abstract T OnCreateItem();/// <summary>/// 获取对象之前(一般用来初始化对象数据)/// </summary>/// <param name="item">对象</param>/// <param name="userData">用户定义数据</param>protected abstract void OnGetBefore(T item, object userData);/// <summary>/// 回收对象时触发/// </summary>/// <param name="item">目标对象</param>/// <returns>是否可以回收</returns>protected abstract bool OnRecycle(T item);/// <summary>/// 销毁对象时触发/// </summary>/// <param name="item">目标对象</param>protected abstract void OnDestroyItem(T item);}

其实到这里就已经写完了,但考虑到有一些同学会问我怎么用???想着尽可能的让你们开箱即食,干脆,咬咬牙,跺跺脚,我再多写200字。
看好了,我要举栗子了…
就以GameObject的对象池为例吧,因为这个的使用频率还是挺高的。
那我们定义一个GameObjectPool来继承IPool,然后再把IPool里的抽象方法都给实现一遍。
喏!,就是这样了:

	public class GameObjectPool : IPool<GameObject>{protected GameObject prefab;public GameObjectPool(GameObject prefab){this.prefab = prefab;}protected override GameObject OnCreateItem(){if (prefab==null){Debug.LogError("GameObjectPool 创建对象失败,prefab不能为null");return null;}return GameObject.Instantiate(prefab);}protected override void OnGetBefore(GameObject item, object userData){item.SetActive(true);}protected override bool OnRecycle(GameObject item){item.SetActive(false);return true;}protected override void OnDestroyItem(GameObject item){GameObject.Destroy(item);}}

好了实现了,怎么样 简单吧。。。。
不是吧 ,都到这里了还要问怎么用。。。。
接着来:

public class Demo : MonoBehaviour
{/// <summary>/// cube预制体/// </summary>public GameObject cubePrefab;/// <summary>/// cube 对象池/// </summary>private GameObjectPool cubePool;//在使用的所有cube,方便一会我要回收它们private List<GameObject> cubes = new List<GameObject>();void Start(){//对象池初始化cubePool = new GameObjectPool(cubePrefab);//预加载5个CubecubePool.PreLoad(5);}private void Update(){//点击空格回收所有的cubeif (Input.GetKeyDown(KeyCode.Space)){cubePool.Recycles(cubes);cubes.Clear();}//点击C 创建一个Cubeif (Input.GetKeyDown(KeyCode.C)){GameObject cube = cubePool.Get();cube.transform.position =GetRandomPos();cubes.Add(cube);}}/// <summary>/// 得到一个随机位置/// </summary>/// <returns></returns>private Vector3 GetRandomPos(){return new Vector3(Random.Range(-10, 10), Random.Range(-10, 10), Random.Range(-10, 10));}}

基本上就是这样了,其它对象的对象池也像GameObjectPool的实现方式,继承IPool 实现所有的抽象方法就可以了。
好了 结束!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/368803.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI免费英语学习在线工具:Pi;gpt;其他大模型AI 英语学习智能体工具

1、pi(强烈推荐&#xff1a;可以安卓下载使用) https://pi.ai/talk &#xff08;网络国内使用方便&#xff09; 支持实时聊天与语音对话 2、chatgpt&#xff08;强烈推荐&#xff1a;可以安卓下载使用) https://chat.openai.com/ &#xff08;网络国内使用不方便&#xf…

2024年显著性检测部分论文及代码汇总(3)

ICML Size-invariance Matters: Rethinking Metrics and Losses for Imbalanced Multi-object Salient Object Detection code Abstacrt&#xff1a;本文探讨了显著性检测中评价指标的尺寸不变性&#xff0c;尤其是当图像中存在多个大小不同的目标时。作者观察到&#xff0c;…

【server】3、注册中心与配置中心

1、服务注册与发现 1.1、consul 1.1.1 是什么 官网&#xff1a; Consul by HashiCorp spring-cloud-consul: Spring Cloud Consul :: Spring Cloud Consul gitHub 官网 &#xff1a;GitHub - hashicorp/consul: Consul is a distributed, highly available, and data cent…

如何在操作使用ufw设置防火墙

UFW&#xff08;简单防火墙&#xff09;是用于管理iptables防火墙规则的用户友好型前端。它的主要目标是使iptables的管理更容易。 在学习Linux的时候大家一般都会关心命令&#xff0c;Posix API和桌面等&#xff0c;很少会去了解防护墙。其实除了一些网络安全厂商提供的付费防…

【设计模式】设计模式学习线路与总结

文章目录 一. 设计原则与思想二. 设计模式与范式三. 设计模式进阶四. 项目实战 设计模式主要是为了改善代码质量&#xff0c;对代码的重用、解耦以及重构给了最佳实践&#xff0c;如下图是我们在掌握设计模式过程中需要掌握和思考的内容概览。 一. 设计原则与思想 面向对象编…

修改头文件版本需要修改的文件

以修改ui的头文件版本为例&#xff0c;还需要同时更新 PJ10PC20240120041_c928\components\master-t5\hikauto\module\app\include PJ10PC20240120041_c928\components\master-t5\hikauto\module\app\include\dsp PJ10PC20240120041_c928\components\master-t5\hikauto\incl…

classin视频下载提取为mp4教程

最近在上classin网课&#xff0c;无奈网课视频要过期了&#xff0c;所以想保存下来&#xff01; 下面介绍提取的教程 我们可以绕过最开始的握手&#xff0c;就是先播放了一段时间后&#xff0c;再打开抓包&#xff0c;回到Classin播放后&#xff0c;就可以获得网课链接了 直接打…

Git安装以及环境配置(详细)

一、Git下载 1.官网&#xff08;但是很慢&#xff09; https://git-scm.com/ 2.镜像版&#xff08;比较推荐&#xff09; CNPM Binaries Mirror 里边多个选择合适的进行下载&#xff08;不要选带有rc0,rc1的&#xff0c;都是预发布版本&#xff09; 进入后如下&#xff0c…

语音大模型引领自然交互新时代,景联文科技推出高质量语音大模型数据库

近期&#xff0c;OpenAI正式发布语音大模型GPT-4o&#xff0c;可以综合利用语音、文本和视觉信息进行推理&#xff0c;扮演一个个人语音交互助手。 在音频处理方面&#xff0c;它不仅能识别和转录多种口音和方言&#xff0c;改变语音的速度音调和振动&#xff0c;还能进行声音模…

vue目录说明

vue目录说明 主要目录说明 .vscode - - -vscode工具的配置文件夹 node_modules - - - vue项目的运行依赖文件夹 public - - -资源文件夹&#xff08;浏览器图标&#xff09; src- - -源码文件夹 .gitignore - - -git忽略文件 index.html - - -入口html文件 package.json - - -…

Golang基础问题

Go基础 文章目录 Go基础● Go有那些关键字&#xff1f;● Go方法与函数的区别&#xff1f;● Go函数返回局部变量的指针是否安全&#xff1f;● Go函数参数传递是值传递还是引用传递&#xff1f;● defer关键字的实现原理&#xff1f;● 内置函数make和new的区别&#xff1f;●…

谷粒商城学习-06-使用vagrant快速创建linux虚拟机

这一节的内容是在Windows上安装虚拟机。 为什么要按照虚拟机呢&#xff1f; 原因是很多软件只能在Linux下运行&#xff0c;有的虽然也可以在Windows上运行&#xff0c;但从安装到运行会遇到很多问题&#xff0c;为这些解决这些问题花时间对于大多数人特别是初学者是没有什么价…

Access,Trunk,Hybrid网络设备链接类型详解

带着问题找答案&#xff1a;网络链路上的数据包怎么看&#xff0c;是否携带vlan-id如何看&#xff0c;以及如何设计链接类型满足用户要求&#xff0c;请看如下解析。 第一种&#xff1a;链接类型access 无标记数据帧 第二种&#xff1a;链接类型trunk 第三种&#xf…

EtherCAT通讯介绍

一、EtherCAT简介 EtherCAT&#xff08;Ethernet for Control Automation Technology&#xff09;是一种实时以太网技术&#xff0c;是由德国公司Beckhoff Automation在2003年首次推出的。它是一种开放的工业以太网标准&#xff0c;被设计用于满足工业自动化应用中的高性能和低…

c++习题09-分离整数的各个数

目录 一&#xff0c;题目 二&#xff0c;思路 三&#xff0c;代码 一&#xff0c;题目 二&#xff0c;思路 一开始我想到的是将简单容易输出的1000以内的数先进行相应的运算&#xff0c;再输出之后再对1000以上的数字进行判断&#xff08;主要还是想先将很大的数变小&#x…

WPF自定义模板--TreeView 实现菜单连接线

有些小伙伴说&#xff0c;在TreeView中&#xff0c;怎么每一个都加上连接线&#xff0c;进行显示连接。 代码和效果如下&#xff1a; 其实就是在原来的模板中增加一列显示线条&#xff0c;然后绘制即可 <Window x:Class"XH.TemplateLesson.TreeViewWindow"xmln…

工具发送formdata请求 Multipartfile 接收

1.需求&#xff1a; 接收到 (Multipartfile file 文件 》使用工具转发到别的请求&#xff0c;将文件传到别的接口 主要代码&#xff1a; InputStreamResource inputstreamResource new InputstreamResource(file.getInputstream(), file.getoriginalfilename());MultiReso…

谷歌地图 | 路线优化 API 助力企业解锁物流新潜能

在当今竞争激烈的市场环境中&#xff0c;企业面临着越来越大的压力&#xff0c;需要提高运营效率、降低成本并满足不断增长的客户期望。对于依赖车队进行交付或服务的企业来说&#xff0c;这些挑战尤为艰巨。 近日&#xff0c; Google 地图平台路线优化 API 已经正式上线。路线…

LTSPICE仿真电路:(十九)磁珠的一些简单仿真

1.作用 简单来说就是用来滤波的&#xff0c;将高频信号转化为热量滤除掉&#xff0c;低频有用信号正常通过 2.参数 上图几个参数比较简单&#xff0c;就是字面上的意思&#xff0c;更重要的就是频率阻抗图 不同曲线代表不同型号的磁珠&#xff0c;实际上除了额定电流外&#…

成都晨持绪:开一家抖音网店到底能不能赚钱

在数字化时代的浪潮中&#xff0c;抖音以其独特的魅力迅速占领了社交媒体的舞台。众多创业者纷纷把目光投向这个新兴平台&#xff0c;企图在短视频的海洋里找到属于自己的财富岛屿。但是&#xff0c;开一家抖音网店到底能不能赚钱呢? 我们要认识到&#xff0c;抖音作为一个流量…