区块链技术博客
www.b2bchain.cn

88.PoolManager(SimpleObjectPool)求职学习资料

D0b2wT.gif

本文介绍了88.PoolManager(SimpleObjectPool)求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

在上一篇,我们完成了 AudioManager ,我们今天再往下接着完成 ManagerOfManagers。
先列出 Manager Of Managers 如下:

  • (完成) MainManager: 作为入口管理器。
  • (已经有了) EventManager: 消息管理。
  • (完成) GUIManager: 图形视图管理。
  • (完成)AudioManager: 音效管理。
  • PoolManager: GameObject管理(减少动态开辟内存消耗,减少GC)。
  • LevelManager: 关卡管理。
  • GameManager: 游戏管理。
  • SaveManager: 配置&存储管理。
  • MenuManager 菜单管理。

我们从这篇文章开始学习 PoolManager,这个其实叫做池管理器,但是呢现在我们连池都没有呢。所以我们先实现一个简单的对象池,关于一个对象池如何发展到一个强大的对象池其实要有很多的路要走,那么我们目前的目的,是全部实现一遍 Manager Of Managers ,只要实现逻辑就够了。其他的,我们第一轮实现之后再想办法逐个优化。

简易对象池

在 Unity 中我们经常会用到对象池,使用对象池无非就是解决两个问题:

  • 一是减少 new 时候寻址造成的消耗,该消耗的原因是内存碎片。
  • 二是减少 Object.Instantiate 时内部进行序列化和反序列化而造成的 CPU 消耗。

想进一步了解对象池模式优化原理的同学可以参阅: 对象池模式:http://gpp.tkchu.me/object-pool.html(http://gpp.tkchu.me/object-pool.html),本篇主要讲如何实现一个精简并且灵活的对象池。

设计

首先我们要弄清楚本篇对象池的几个概念,否则直接上代码大家会一头雾水。
从字面上理解对象池,池的意思就是容器。我们可以从池中获取一个对象 (一条鱼),也可以向池中放入一个对象 (一条鱼)。获取的操作我们叫 Allocate(分配),而放入一个对象我们叫 Recycle(回收)(ps:也有很多习惯叫 Spawn 和 Despawn 的,这个看自己习惯了)。所以我们可以定义池的接口为如下:

    public interface IPool<T>     {         T Allocate();          bool Recycle(T obj);     }

为什么要用泛型呢?因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过泛型体现的。

前面有说过,池是容器的意思,在 C# 中可以是 List,Queue 或者 Stack 甚至是数组。所以对象池本身要维护一个容器。本篇我们选取 Stack 来作为池容器,原因是当我们在 Allocate 和 Recycle 时并不关心缓存的存储的顺序,只要求缓存对象的地址是连续的。代码如下所示:

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {           ...         protected Stack<T> mCacheStack = new Stack<T>();           ...     }

Pool 是个抽象类,为什么呢? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过抽象类体现的。

现在对象的存取和缓存接口都设计好了,那么这些对象是从哪里来的呢?我们分析下,创建对象我们知道有两种方式,反射构造方法和 new 一个对象。对象池的一个重要功能就是缓存,要想实现缓存就要求对象可以在对象池内部进行创建。所以我们要抽象出一个对象的工厂,代码如下所示:

    public interface IObjectFactory<T>     {         T Create();     }

那么大家要问为什么要用工厂? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过工厂体现的。

OK,现在对象的创建,存取,缓存的接口都设计好了。下面放出Pool的全部代码。

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {         #region ICountObserverable         /// <summary>         /// Gets the current count.         /// </summary>         /// <value>The current count.</value>         public int CurCount         {             get { return mCacheStack.Count; }         }         #endregion          protected IObjectFactory<T> mFactory;          protected Stack<T> mCacheStack = new Stack<T>();          /// <summary>         /// default is 5         /// </summary>         protected int mMaxCount = 5;          public virtual T Allocate()         {             return mCacheStack.Count == 0                 ? mFactory.Create()                 : mCacheStack.Pop();         }          public abstract bool Recycle(T obj);     }

代码不多,设计阶段基本就这样。下面介绍如何实现一个简易的对象池。

对象池实现

首先要实现一个对象的创建器,代码如下所示:

    using System;      public class CustomObjectFactory<T> : IObjectFactory<T>     {         public CustomObjectFactory(Func<T> factoryMethod)         {             mFactoryMethod = factoryMethod;         }          protected Func<T> mFactoryMethod;          public T Create()         {             return mFactoryMethod();         }     }

比较简单,只是维护了一个返回值为T的委托(如果说得有误请指正)。
对象池实现:

     /// <summary>     /// unsafe but fast     /// </summary>     /// <typeparam name="T"></typeparam>     public class SimpleObjectPool<T> : Pool<T>     {         readonly Action<T> mResetMethod;          public SimpleObjectPool(Func<T> factoryMethod, Action<T> resetMethod = null,int initCount = 0)         {             mFactory = new CustomObjectFactory<T>(factoryMethod);             mResetMethod = resetMethod;              for (var i = 0; i < initCount; i++)             {                 mCacheStack.Push(mFactory.Create());             }         }          public override bool Recycle(T obj)         {             if (mResetMethod != null)             {                 mResetMethod(obj);             }              mCacheStack.Push(obj);             return true;         }     }

实现也很简单,这里不多说了。

贴出全部的代码:

在上一篇,我们完成了 AudioManager ,我们今天再往下接着完成 ManagerOfManagers。
先列出 Manager Of Managers 如下:

  • (完成) MainManager: 作为入口管理器。
  • (已经有了) EventManager: 消息管理。
  • (完成) GUIManager: 图形视图管理。
  • (完成)AudioManager: 音效管理。
  • PoolManager: GameObject管理(减少动态开辟内存消耗,减少GC)。
  • LevelManager: 关卡管理。
  • GameManager: 游戏管理。
  • SaveManager: 配置&存储管理。
  • MenuManager 菜单管理。

我们从这篇文章开始学习 PoolManager,这个其实叫做池管理器,但是呢现在我们连池都没有呢。所以我们先实现一个简单的对象池,关于一个对象池如何发展到一个强大的对象池其实要有很多的路要走,那么我们目前的目的,是全部实现一遍 Manager Of Managers ,只要实现逻辑就够了。其他的,我们第一轮实现之后再想办法逐个优化。

简易对象池

在 Unity 中我们经常会用到对象池,使用对象池无非就是解决两个问题:

  • 一是减少 new 时候寻址造成的消耗,该消耗的原因是内存碎片。
  • 二是减少 Object.Instantiate 时内部进行序列化和反序列化而造成的 CPU 消耗。

想进一步了解对象池模式优化原理的同学可以参阅: 对象池模式:http://gpp.tkchu.me/object-pool.html(http://gpp.tkchu.me/object-pool.html),本篇主要讲如何实现一个精简并且灵活的对象池。

设计

首先我们要弄清楚本篇对象池的几个概念,否则直接上代码大家会一头雾水。
从字面上理解对象池,池的意思就是容器。我们可以从池中获取一个对象 (一条鱼),也可以向池中放入一个对象 (一条鱼)。获取的操作我们叫 Allocate(分配),而放入一个对象我们叫 Recycle(回收)(ps:也有很多习惯叫 Spawn 和 Despawn 的,这个看自己习惯了)。所以我们可以定义池的接口为如下:

    public interface IPool<T>     {         T Allocate();          bool Recycle(T obj);     }

为什么要用泛型呢?因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过泛型体现的。

前面有说过,池是容器的意思,在 C# 中可以是 List,Queue 或者 Stack 甚至是数组。所以对象池本身要维护一个容器。本篇我们选取 Stack 来作为池容器,原因是当我们在 Allocate 和 Recycle 时并不关心缓存的存储的顺序,只要求缓存对象的地址是连续的。代码如下所示:

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {           ...         protected Stack<T> mCacheStack = new Stack<T>();           ...     }

Pool 是个抽象类,为什么呢? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过抽象类体现的。

现在对象的存取和缓存接口都设计好了,那么这些对象是从哪里来的呢?我们分析下,创建对象我们知道有两种方式,反射构造方法和 new 一个对象。对象池的一个重要功能就是缓存,要想实现缓存就要求对象可以在对象池内部进行创建。所以我们要抽象出一个对象的工厂,代码如下所示:

    public interface IObjectFactory<T>     {         T Create();     }

那么大家要问为什么要用工厂? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过工厂体现的。

OK,现在对象的创建,存取,缓存的接口都设计好了。下面放出Pool的全部代码。

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {         #region ICountObserverable         /// <summary>         /// Gets the current count.         /// </summary>         /// <value>The current count.</value>         public int CurCount         {             get { return mCacheStack.Count; }         }         #endregion          protected IObjectFactory<T> mFactory;          protected Stack<T> mCacheStack = new Stack<T>();          /// <summary>         /// default is 5         /// </summary>         protected int mMaxCount = 5;          public virtual T Allocate()         {             return mCacheStack.Count == 0                 ? mFactory.Create()                 : mCacheStack.Pop();         }          public abstract bool Recycle(T obj);     }

代码不多,设计阶段基本就这样。下面介绍如何实现一个简易的对象池。

对象池实现

首先要实现一个对象的创建器,代码如下所示:

    using System;      public class CustomObjectFactory<T> : IObjectFactory<T>     {         public CustomObjectFactory(Func<T> factoryMethod)         {             mFactoryMethod = factoryMethod;         }          protected Func<T> mFactoryMethod;          public T Create()         {             return mFactoryMethod();         }     }

比较简单,只是维护了一个返回值为T的委托(如果说得有误请指正)。
对象池实现:

     /// <summary>     /// unsafe but fast     /// </summary>     /// <typeparam name="T"></typeparam>     public class SimpleObjectPool<T> : Pool<T>     {         readonly Action<T> mResetMethod;          public SimpleObjectPool(Func<T> factoryMethod, Action<T> resetMethod = null,int initCount = 0)         {             mFactory = new CustomObjectFactory<T>(factoryMethod);             mResetMethod = resetMethod;              for (var i = 0; i < initCount; i++)             {                 mCacheStack.Push(mFactory.Create());             }         }          public override bool Recycle(T obj)         {             if (mResetMethod != null)             {                 mResetMethod(obj);             }              mCacheStack.Push(obj);             return true;         }     }

实现也很简单,这里不多说了。

贴出全部的代码:

在上一篇,我们完成了 AudioManager ,我们今天再往下接着完成 ManagerOfManagers。
先列出 Manager Of Managers 如下:

  • (完成) MainManager: 作为入口管理器。
  • (已经有了) EventManager: 消息管理。
  • (完成) GUIManager: 图形视图管理。
  • (完成)AudioManager: 音效管理。
  • PoolManager: GameObject管理(减少动态开辟内存消耗,减少GC)。
  • LevelManager: 关卡管理。
  • GameManager: 游戏管理。
  • SaveManager: 配置&存储管理。
  • MenuManager 菜单管理。

我们从这篇文章开始学习 PoolManager,这个其实叫做池管理器,但是呢现在我们连池都没有呢。所以我们先实现一个简单的对象池,关于一个对象池如何发展到一个强大的对象池其实要有很多的路要走,那么我们目前的目的,是全部实现一遍 Manager Of Managers ,只要实现逻辑就够了。其他的,我们第一轮实现之后再想办法逐个优化。

简易对象池

在 Unity 中我们经常会用到对象池,使用对象池无非就是解决两个问题:

  • 一是减少 new 时候寻址造成的消耗,该消耗的原因是内存碎片。
  • 二是减少 Object.Instantiate 时内部进行序列化和反序列化而造成的 CPU 消耗。

想进一步了解对象池模式优化原理的同学可以参阅: 对象池模式:http://gpp.tkchu.me/object-pool.html(http://gpp.tkchu.me/object-pool.html),本篇主要讲如何实现一个精简并且灵活的对象池。

设计

首先我们要弄清楚本篇对象池的几个概念,否则直接上代码大家会一头雾水。
从字面上理解对象池,池的意思就是容器。我们可以从池中获取一个对象 (一条鱼),也可以向池中放入一个对象 (一条鱼)。获取的操作我们叫 Allocate(分配),而放入一个对象我们叫 Recycle(回收)(ps:也有很多习惯叫 Spawn 和 Despawn 的,这个看自己习惯了)。所以我们可以定义池的接口为如下:

    public interface IPool<T>     {         T Allocate();          bool Recycle(T obj);     }

为什么要用泛型呢?因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过泛型体现的。

前面有说过,池是容器的意思,在 C# 中可以是 List,Queue 或者 Stack 甚至是数组。所以对象池本身要维护一个容器。本篇我们选取 Stack 来作为池容器,原因是当我们在 Allocate 和 Recycle 时并不关心缓存的存储的顺序,只要求缓存对象的地址是连续的。代码如下所示:

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {           ...         protected Stack<T> mCacheStack = new Stack<T>();           ...     }

Pool 是个抽象类,为什么呢? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过抽象类体现的。

现在对象的存取和缓存接口都设计好了,那么这些对象是从哪里来的呢?我们分析下,创建对象我们知道有两种方式,反射构造方法和 new 一个对象。对象池的一个重要功能就是缓存,要想实现缓存就要求对象可以在对象池内部进行创建。所以我们要抽象出一个对象的工厂,代码如下所示:

    public interface IObjectFactory<T>     {         T Create();     }

那么大家要问为什么要用工厂? 因为笔者开头说过,本篇主要讲如何实现一个精简并且灵活的对象池。这个灵活很大一部分是通过工厂体现的。

OK,现在对象的创建,存取,缓存的接口都设计好了。下面放出Pool的全部代码。

    using System.Collections.Generic;      public abstract class Pool<T> : IPool<T>     {         #region ICountObserverable         /// <summary>         /// Gets the current count.         /// </summary>         /// <value>The current count.</value>         public int CurCount         {             get { return mCacheStack.Count; }         }         #endregion          protected IObjectFactory<T> mFactory;          protected Stack<T> mCacheStack = new Stack<T>();          /// <summary>         /// default is 5         /// </summary>         protected int mMaxCount = 5;          public virtual T Allocate()         {             return mCacheStack.Count == 0                 ? mFactory.Create()                 : mCacheStack.Pop();         }          public abstract bool Recycle(T obj);     }

代码不多,设计阶段基本就这样。下面介绍如何实现一个简易的对象池。

对象池实现

首先要实现一个对象的创建器,代码如下所示:

    using System;      public class CustomObjectFactory<T> : IObjectFactory<T>     {         public CustomObjectFactory(Func<T> factoryMethod)         {             mFactoryMethod = factoryMethod;         }          protected Func<T> mFactoryMethod;          public T Create()         {             return mFactoryMethod();         }     }

比较简单,只是维护了一个返回值为T的委托(如果说得有误请指正)。
对象池实现:

     /// <summary>     /// unsafe but fast     /// </summary>     /// <typeparam name="T"></typeparam>     public class SimpleObjectPool<T> : Pool<T>     {         readonly Action<T> mResetMethod;          public SimpleObjectPool(Func<T> factoryMethod, Action<T> resetMethod = null,int initCount = 0)         {             mFactory = new CustomObjectFactory<T>(factoryMethod);             mResetMethod = resetMethod;              for (var i = 0; i < initCount; i++)             {                 mCacheStack.Push(mFactory.Create());             }         }          public override bool Recycle(T obj)         {             if (mResetMethod != null)             {                 mResetMethod(obj);             }              mCacheStack.Push(obj);             return true;         }     }

实现也很简单,这里不多说了。

贴出全部的代码:

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 88.PoolManager(SimpleObjectPool)求职学习资料
分享到: 更多 (0)
D0b2wT.gif

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们