创建一个接口,用于限定对象池中所保存的对象的基本行为:
public interface IDynamicObject { void Create(Object param); Object GetInnerObject(); bool IsValidate(); void Release(); }
|
我们在对象池中存放的对象,必须继承上面的接口,并实现接口定义的每一个方法。
Create方法中,用户可以用来创建实际的对象,如建立数据库连接,并打开这个连接;GetInnerObject方法,使用户可以返回这个实际的对象,如一个SqlConnection对象;IsValidate方法是用来判断用户自定义对象的有效性的,是对象池决定是否重新创建对象的标志;Release方法中,用户可以进行资源释放工作。
有了上面的接口定义,为我们可以在列表中保存用户自定义对象打下了基础。下面就是要实现这个ObjectPool了。
用户自定义对象在我们的ObjectPool中,可以用列表存储,如ArrayList或者Hashtable,为了表示每个用户对象的状态,我们还需要将用户自定义对象包装一下,然后在放到列表中保存。下面定义了一个ObjectPool类的子类,用于包装用户自定义对象:
private class PoolItem { private IDynamicObject _object; private bool _bUsing; private Type _type; private Object _CreateParam;
public PoolItem(Type type,Object param) { _type = type; _CreateParam = param; Create(); }
private void Create() { _bUsing = false;
_object = (IDynamicObject)System.Activator.CreateInstance(_type); _object.Create(_CreateParam);
} public void Recreate() { _object.Release(); Create(); } public void Release() { _object.Release(); } public Object InnerObject { get{return _object.GetInnerObject();} } public int InnerObjectHashcode { get{return InnerObject.GetHashCode();} } public bool IsValidate { get{return _object.IsValidate();} } public bool Using { get{return _bUsing;} set { _bUsing = value; } } }// class PoolItem
|
这个类,一个关键的属性是Using,该属性表示对象是否正在被被用户使用。注意,PoolItem创建时,接受一个Object类型的Param参数,这个参数最后被传递给用户自定义对象的Create方法。用户可以利用这一点,在创建ObjectPool时指定一些参数,供其自定义对象在创建时使用。比如创建SocketPool时,将服务器IP,端口通过Param传递给自定义对象的Create方法,用户就可以在Create方法中连接指定的服务器了。
以下是ObjectPool的具体实现代码:
public sealed class ObjectPool { private Int32 _nCapacity; private Int32 _nCurrentSize; private Hashtable _listObjects; private ArrayList _listFreeIndex; private ArrayList _:listUsingIndex; private Type _typeObject; private Object _objCreateParam;
public ObjectPool(Type type, Object create_param, Int32 init_size, Int32 capacity) { if(init_size < 0 || capacity < 1 || init_size>capacity) { throw(new Exception("Invalid parameter!")); }
_nCapacity = capacity; _listObjects = new Hashtable(capacity); _listFreeIndex = new ArrayList(capacity); _listUsingIndex = new ArrayList(capacity); _typeObject = type; _objCreateParam = create_param;
for(int i=0;i<init_size;i++) { PoolItem pitem = new PoolItem(type,create_param); _listObjects.Add(pitem.InnerObjectHashcode,pitem); _listFreeIndex.Add(pitem.InnerObjectHashcode); }
_nCurrentSize = _listObjects.Count; }
public void Release() { lock(this) { foreach(DictionaryEntry de in _listObjects) { ( (PoolItem)de.Value ).Release(); } _listObjects.Clear(); _listFreeIndex.Clear(); _listUsingIndex.Clear(); } }
public Int32 CurrentSize { get{return _nCurrentSize;} }
public Int32 ActiveCount { get{return _listUsingIndex.Count;} }
public Object GetOne() { lock(this) { if(_listFreeIndex.Count == 0) { if(_nCurrentSize == _nCapacity) { return null; }
PoolItem pnewitem = new PoolItem(_typeObject,_objCreateParam); _listObjects.Add(pnewitem.InnerObjectHashcode,pnewitem); _listFreeIndex.Add(pnewitem.InnerObjectHashcode); _nCurrentSize++; }
Int32 nFreeIndex = (Int32)_listFreeIndex[0]; PoolItem pitem = (PoolItem)_listObjects[nFreeIndex]; _listFreeIndex.RemoveAt(0); _listUsingIndex.Add(nFreeIndex);
if(!pitem.IsValidate) { pitem.Recreate(); } pitem.Using = true;
return pitem.InnerObject; } }
public void FreeObject(Object obj) { lock(this) { int key = obj.GetHashCode(); if(_listObjects.ContainsKey(key)) { PoolItem item = (PoolItem)_listObjects[key]; item.Using = false; _listUsingIndex.Remove(key); _listFreeIndex.Add(key); } } }
public Int32 DecreaseSize(Int32 size) { Int32 nDecrease = size; lock(this) { if(nDecrease <= 0) { return 0; } if(nDecrease > _listFreeIndex.Count) { nDecrease = _listFreeIndex.Count; } for(int i=0;i<nDecrease;i++) { _listObjects.Remove(_listFreeIndex[i]); }
_listFreeIndex.Clear(); _listUsingIndex.Clear();
foreach(DictionaryEntry de in _listObjects) { PoolItem pitem = (PoolItem)de.Value; if(pitem.Using) { _listUsingIndex.Add(pitem.InnerObjectHashcode); } else { _listFreeIndex.Add(pitem.InnerObjectHashcode); } }
} _nCurrentSize -= nDecrease; return nDecrease; } }
|
下篇再给出一个用这个ObjectPool实现的数据库连接池的例子。