In the last post I discussed the Multiton pattern and this post continues the theme of non-GoF patterns by looking at Object Pool, another specialised Singleton. The purpose of this pattern is to re-use object instances to avoid creation / destruction. My mnemonic this time is a Car Pool which is just a collection of cars for my purposes:
public sealed class Car
{
public Car(string registration)
{
this.Registration = registration;
}
public string Registration
{
get;
set;
}
public override string ToString()
{
return this.Registration;
}
}The pool implementation also uses weak references to handle garbage collected cars which have not been explicitly returned to the pool:
using System;
using System.Collections.Generic;
using System.Linq;
public sealed class CarPool
{
private static CarPool _pool = new CarPool();
private CarPool()
{
this.Cars = new Dictionary<Car, WeakReference>();
}
public static int Availability
{
get
{
int value = 0;
lock (_pool)
{
value = _pool.Cars.Where(x => null == x.Value || !x.Value.IsAlive).Count();
}
return value;
}
}
private Dictionary<Car, WeakReference> Cars
{
get;
set;
}
public static void Add(params Car[] cars)
{
foreach (var car in cars)
{
lock (_pool)
{
_pool.Add(car);
}
}
}
public static Car Get()
{
Car result = null;
if (0 < CarPool.Availability)
{
lock (_pool)
{
var item = _pool.Cars.Where(x => null == x.Value || !x.Value.IsAlive).FirstOrDefault();
var value = new WeakReference(item.Key);
_pool.Cars[item.Key] = value;
result = (Car)value.Target;
}
}
return result;
}
public static void Return(Car car)
{
if (null == car)
{
throw new ArgumentNullException("car");
}
lock (_pool)
{
_pool.Cars[car] = null;
}
}
private void Add(Car car)
{
this.Cars.Add(car, new WeakReference(null));
}
}Here is a test which verifies the expected behaviour:
using Xunit;
public sealed class ObjectPoolFacts
{
[Fact]
public void car_pooling()
{
Car one = new Car("ABC 111");
Car two = new Car("ABC 222");
CarPool.Add(one, two);
Car first = CarPool.Get();
Assert.Same(one, first);
Car second = CarPool.Get();
Assert.Same(two, second);
Assert.Null(CarPool.Get());
CarPool.Return(first);
CarPool.Return(second);
second = CarPool.Get();
Assert.Same(one, second);
}
}


Over the last couple of months I have been thinking about 








