Object Pool Design Pattern

What is object pool?

 
As a developer we might have noticed that creation of some class is very difficult and number of time that we need to create. Such object creation every time is very expensive in terms of system resources. If we can cache that kind of object show how will surely boost the application performance and resource usage can be saved. This where object pool design pattern will help development community to cache the objects. Some time it is also called as Object cache or Resource cache design pattern.
 
It is adviced to keep all Reusable expensive objects that are not currently in use in the container so that they can be managed by one rational policy. To achieve this, the Reusable Pool class is designed to be a singleton class.
 

Queue Class

 
Queue is a Simple DataStucture which allows Add or Remove of Items at one of the ends only. It is basically called as First in First out data structure. The item which is added first is the first one to be removed. Default initial size of the queue is 32. Make sure that whenever Queue is initialized define the size of the queue, that Add and Remove operations are performed perfectly.
 
Enqueue () method will add the item in the last available portion and Dequeue () method will remove and return the oldest item in the queue. Set us see the code how it helps to implement the object pool design pattern.
 
EX: Simple Example
  1. public class QueuedPool: Queue  
  2. {  
  3.     public Person Fetch()  
  4.     {  
  5.         return (Person)Dequeue();  
  6.     }  
  7.     public void Store(Person person)  
  8.     {  
  9.         Enqueue(person);  
  10.     }  
  11.     public void ClearAll()  
  12.     {  
  13.         base.Clear();  
  14.     }  
  15. }  
At client side - Using Generics
  1. QueuedPool queuePool = new QueuedPool();  
  2. queuePool.Store(new Person());  
  3. Person p = queuePool.Fetch();  
  4. public interface IStore<T>  
  5. {  
  6.     T Fetch();  
  7.     void Store(T obj);  
  8.     int Count { get;}  
  9.     void ClearAll();  
  10. }  
  11. public class QueuedPool<T> : Queue<T>, IStore<T>  
  12. {  
  13.     public T Fetch()  
  14.     {  
  15.         return (T)Dequeue();  
  16.     }  
  17.     public void Store(T obj)  
  18.     {  
  19.         Enqueue(obj);  
  20.     }  
  21.     public void ClearAll()  
  22.     {  
  23.         base.Clear();  
  24.     }  
  25. }  
At client side - Thread Safe Example
  1. QueuedPool<Person> queuePool = new QueuedPool<Person>();  
  2. queuePool.Store(new Person());  
  3. Person p = queuePool.Fetch();  
  4. public sealed class ObjectPoolObject<T> where T : new()  
  5. {  
  6.     private readonly int _poolSize;  
  7.     private readonly object _threadLocker;  
  8.     private readonly Queue<T> _poolManager;  
  9.     public ObjectPoolObject(int expectedPoolSize)  
  10.     {  
  11.         if (expectedPoolSize <= 0)  
  12.             throw new ArgumentOutOfRangeException("expectedPoolSize""Pool size can't be null or zero or less than zero");  
  13.         _poolManager = new Queue<T>();  
  14.         _threadLocker = new object();  
  15.         _poolSize = expectedPoolSize;  
  16.     }  
  17.   
  18.     public T Get()  
  19.     {  
  20.         lock (_threadLocker)  
  21.         {  
  22.             if (_poolManager.Count > 0)  
  23.             {  
  24.                  return _poolManager.Dequeue();  
  25.             }  
  26.             else  
  27.             {  
  28.                 return new T();  
  29.             }  
  30.         }  
  31.     }  
  32.   
  33.     public int Count()  
  34.     {  
  35.         return _poolManager.Count;  
  36.     }  
  37.   
  38.     public void Put(T obj)  
  39.     {   
  40.         lock(_threadLocker)  
  41.         {  
  42.             if (_poolManager.Count < _poolSize)  
  43.                 _poolManager.Enqueue(obj);  
  44.         }  
  45.      }  
  46. }  
At client side
  1. ObjectPoolObject<Person> personPoolObject = new ObjectPoolObject<Person>(10);  
  2. Person a = personPoolObject.Get();  
  3. Person a1 = personPoolObject.Get();  
  4.   
  5. addressPoolObject.Put(a);  
  6. addressPoolObject.Put(a1);  
Best candidates for 
  1. Any ticketing counter, who goes first those, gets ticks first. 
  2. Who places order first they get served first.
Now let us continue with other options available in C#
 

Stack Class

 
The Stack class implements a Last in First Out data structure. The objects are stored in such a manner that the object added last is placed at the top of the stack.
 
Push () method adds new item to stack on the top of all items. Pop () method removes the top item in the items list.
  1. public class StackPool<T>: Stack<T>, IStore<T>  
  2. {  
  3.     public T Fetch()  
  4.     {  
  5.         return Pop();  
  6.     }  
  7.   
  8.     public void Store(T obj)  
  9.     {  
  10.         Push(obj);  
  11.     }  
  12.   
  13.     public void ClearAll()  
  14.     {  
  15.         Clear();  
  16.     }  
  17. }  
At client
  1. StackPool<Person> personStackPool = new StackPool<Person>();  
  2.   
  3. personStackPool.Store(new Address());  
  4. personStackPool.Store(new Address());  
  5.   
  6. Person p1 = personStackPool.Fetch();  
  7. Person p2 = personStackPool.Fetch();  

Singleton Example

  1.  public sealed class ObjectPoolObject<T> where T : new()  
  2.  {  
  3.      private readonly object _threadLocker = new object();  
  4.      private readonly Queue<T> _poolManager = new Queue<T>();  
  5.      private static ObjectPoolObject<T> _objectPoolObject;  
  6.      private ObjectPoolObject() { }  
  7.   
  8.      static ObjectPoolObject()   
  9.      {  
  10.          _objectPoolObject = new ObjectPoolObject<T>();   
  11.      }  
  12.   
  13.      public static ObjectPoolObject<T> GetInstance()  
  14.      {  
  15.          return _objectPoolObject;  
  16.      }  
  17.   
  18.      public T Get()  
  19.      {  
  20.          lock (_threadLocker)  
  21.          {  
  22.              if (_poolManager.Count > 0)  
  23.              {  
  24.                   return _poolManager.Dequeue();  
  25.              }  
  26.              else  
  27.              {  
  28.                  return new T();  
  29.              }  
  30.          }  
  31.      }  
  32.   
  33.      public int Count()  
  34.      {  
  35.          return _poolManager.Count;  
  36.      }  
  37.   
  38.      public void Put(T obj)  
  39.      {   
  40.          lock(_threadLocker)  
  41.          {  
  42.              _poolManager.Enqueue(obj);  
  43.          }  
  44.   
  45.       }  
  46. }  
  47. public class Person  
  48. {  
  49.      private string _firstName;  
  50.      private string _middleInitial;  
  51.      private string _lastName;  
  52.   
  53.      public string FirstName  
  54.      {  
  55.          get { return _firstName;}  
  56.          set { _firstName = value; }  
  57.      }  
  58.      public string MiddleInitial  
  59.      {  
  60.          get { return _middleInitial;}  
  61.          set { _middleInitial = value; }  
  62.      }  
  63.      public string LastName  
  64.      {  
  65.          get { return _lastName;}  
  66.          set { _lastName = value; }  
  67.      }  
  68.      public Person() { }