Pool

思考并回答以下问题:

Pool

ObjectFactory

IObjectFactory.cs

1
2
3
4
5
6
7
8
9
10
namespace QF
{
// 接口声明可以有任何的访问修饰符public、protected、internal或private。
public interface IObjectFactory<T>
{
// 接口的成员是隐式public的,不允许有任何访问修饰符,包括public。
// 函数成员的声明不能包含任何实现代码,而在每一个成员声明的主体后必须使用分号。
T Create();
}
}

DefaultObjectFactory.cs

1
2
3
4
5
6
7
8
9
10
namespace QF
{
public class DefaultObjectFactory<T> : IObjectFactory<T> where T : new()
{
public T Create()
{
return new T();
}
}
}

CustomObjectFactory.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace QF
{
using System;

public class CustomObjectFactory<T> : IObjectFactory<T>
{
// 带返回类型的委托
// 无参数时:Func<TResult> Func<返回值>
// 有参数时:Func<TParam, TResult> Func<参数类型, 返回值>
protected Func<T> mFactoryMethod;

public CustomObjectFactory(Func<T> factoryMethod)
{
mFactoryMethod = factoryMethod;
}

public T Create()
{
// 执行委托
return mFactoryMethod();
}
}
}

NonPublicObjectFactory.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace QF
{
using System;
using System.Reflection;

// class约束:任何引用类型,包括类(静态类和非静态类)、数组、委托和接口都可以用作类型实参
public class NonPublicObjectFactory<T> : IObjectFactory<T> where T : class
{
public T Create()
{
// 得到所有构造函数
var ctors = typeof(T).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);

// 寻找到无参私有构造函数
var ctor = Array.Find(ctors, c => c.GetParameters().Length == 0);
return ctor.Invoke(null) as T;
}
}
}

Pool

IPool.cs

1
2
3
4
5
6
7
8
9
namespace QF
{
public interface IPool<T>
{
T Allocate();

bool Recycle(T obj);
}
}

Pool.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

namespace QF
{
using System.Collections.Generic;

public abstract class Pool<T> : IPool<T>,ICountObserveAble
{
#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 readonly Stack<T> mCacheStack = new Stack<T>();

/// <summary>
/// default is 5
/// </summary>
protected int mMaxCount = 12;

public virtual T Allocate()
{
return mCacheStack.Count == 0
? mFactory.Create()
: mCacheStack.Pop();
}

public abstract bool Recycle(T obj);
}
}

NonPublicObjectPool.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
namespace QF
{
using System;

/// <summary>
/// Object pool 4 class who no public constructor
/// such as SingletonClass.QEventSystem
/// </summary>
public class NonPublicObjectPool<T> :Pool<T>,ISingleton where T : class,IPoolable
{
#region Singleton
public void OnSingletonInit(){}

public static NonPublicObjectPool<T> Instance
{
get { return SingletonProperty<NonPublicObjectPool<T>>.Instance; }
}

protected NonPublicObjectPool()
{
mFactory = new NonPublicObjectFactory<T>();
}

public void Dispose()
{
SingletonProperty<NonPublicObjectPool<T>>.Dispose();
}
#endregion

/// <summary>
/// Init the specified maxCount and initCount.
/// </summary>
/// <param name="maxCount">Max Cache count.</param>
/// <param name="initCount">Init Cache count.</param>
public void Init(int maxCount, int initCount)
{
if (maxCount > 0)
{
initCount = Math.Min(maxCount, initCount);
}

if (CurCount >= initCount) return;

for (var i = CurCount; i < initCount; ++i)
{
Recycle(mFactory.Create());
}
}

/// <summary>
/// Gets or sets the max cache count.
/// </summary>
/// <value>The max cache count.</value>
public int MaxCacheCount
{
get { return mMaxCount; }
set
{
mMaxCount = value;

if (mCacheStack == null) return;
if (mMaxCount <= 0) return;
if (mMaxCount >= mCacheStack.Count) return;
var removeCount = mMaxCount - mCacheStack.Count;
while (removeCount > 0)
{
mCacheStack.Pop();
--removeCount;
}
}
}

/// <summary>
/// Allocate T instance.
/// </summary>
public override T Allocate()
{
var result = base.Allocate();
result.IsRecycled = false;
return result;
}

/// <summary>
/// Recycle the T instance
/// </summary>
/// <param name="t">T.</param>
public override bool Recycle(T t)
{
if (t == null || t.IsRecycled)
{
return false;
}

if (mMaxCount > 0)
{
if (mCacheStack.Count >= mMaxCount)
{
t.OnRecycled();
return false;
}
}

t.IsRecycled = true;
t.OnRecycled();
mCacheStack.Push(t);

return true;
}
}
}

SimpleObjectPool.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespace QF
{
using System;

/// <summary>
/// Unity 游戏框架搭建 (十九) 简易对象池:http://qframework.io/post/24/ 的例子
/// </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 (int i = 0; i < initCount; i++)
{
mCacheStack.Push(mFactory.Create());
}
}

public override bool Recycle(T obj)
{
if (mResetMethod != null)
{
mResetMethod.Invoke(obj);
}

mCacheStack.Push(obj);
return true;
}
}
}

SafeObjectPool.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
namespace QF
{
using System;

/// <summary>
/// I cache type.
/// </summary>
public interface IPoolType
{
void Recycle2Cache();
}

/// <summary>
/// I pool able.
/// </summary>
public interface IPoolable
{
void OnRecycled();
bool IsRecycled { get; set; }
}

/// <summary>
/// Count observer able.
/// </summary>
public interface ICountObserveAble
{
int CurCount { get; }
}

/// <summary>
/// Object pool.
/// </summary>
public class SafeObjectPool<T> : Pool<T>, ISingleton where T : IPoolable, new()
{
#region Singleton
void ISingleton.OnSingletonInit() {}

protected SafeObjectPool()
{
mFactory = new DefaultObjectFactory<T>();
}

public static SafeObjectPool<T> Instance
{
get { return SingletonProperty<SafeObjectPool<T>>.Instance; }
}

public void Dispose()
{
SingletonProperty<SafeObjectPool<T>>.Dispose();
}
#endregion

/// <summary>
/// Init the specified maxCount and initCount.
/// </summary>
/// <param name="maxCount">Max Cache count.</param>
/// <param name="initCount">Init Cache count.</param>
public void Init(int maxCount, int initCount)
{
MaxCacheCount = maxCount;

if (maxCount > 0)
{
initCount = Math.Min(maxCount, initCount);
}

if (CurCount < initCount)
{
for (var i = CurCount; i < initCount; ++i)
{
Recycle(new T());
}
}
}

/// <summary>
/// Gets or sets the max cache count.
/// </summary>
/// <value>The max cache count.</value>
public int MaxCacheCount
{
get { return mMaxCount; }
set
{
mMaxCount = value;

if (mCacheStack != null)
{
if (mMaxCount > 0)
{
if (mMaxCount < mCacheStack.Count)
{
int removeCount = mCacheStack.Count - mMaxCount;
while (removeCount > 0)
{
mCacheStack.Pop();
--removeCount;
}
}
}
}
}
}

/// <summary>
/// Allocate T instance.
/// </summary>
public override T Allocate()
{
var result = base.Allocate();
result.IsRecycled = false;
return result;
}

/// <summary>
/// Recycle the T instance
/// </summary>
/// <param name="t">T.</param>
public override bool Recycle(T t)
{
if (t == null || t.IsRecycled)
{
return false;
}

if (mMaxCount > 0)
{
if (mCacheStack.Count >= mMaxCount)
{
t.OnRecycled();
return false;
}
}

t.IsRecycled = true;
t.OnRecycled();
mCacheStack.Push(t);

return true;
}
}
}

Cache

SimpleObjectCache.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
namespace QF
{
using System;
using System.Collections.Generic;

public class SimpleObjectCache
{
private readonly Dictionary<Type, object> mObjectPools;

public SimpleObjectCache()
{
mObjectPools = new Dictionary<Type, object>();
}

public SimpleObjectPool<T> GetObjectPool<T>() where T : new()
{
object objectPool;
var type = typeof(T);
if (!mObjectPools.TryGetValue(type, out objectPool))
{
objectPool = new SimpleObjectPool<T>(() => new T());
mObjectPools.Add(type, objectPool);
}

return ((SimpleObjectPool<T>) objectPool);
}

public T Get<T>() where T : new()
{
return GetObjectPool<T>().Allocate();
}

public void Push<T>(T obj) where T : new()
{
GetObjectPool<T>().Recycle(obj);
}

public void RegisterCustomObjectPool<T>(SimpleObjectPool<T> simpleObjectPool)
{
mObjectPools.Add(typeof(T), simpleObjectPool);
}

public void Reset()
{
mObjectPools.Clear();
}
}
}
0%