I have a GUI application. In it I allow a user to select from a container-provided list of algorithms. Each algorithm will be kicked off as a background task in another view.
I always like to show general answers, without going to much into features of special containers. You say the following:
Using a factory is probably the best approach. The second requirement can be solved by returning IDisposable
objects. You can then write code like this:
using (var algorithm = this.algoFactory.CreateNew(type))
{
// use algorithm.
}
There are multiple ways of doing this, but you can let the algorithm interface implement IDisposable
:
public interface IAlgorithm : IDisposable
{
}
Instead of returning the real algorithm, you can return an decorator, that allows that instance to be returned to the pool:
public sealed class PooledAlgorithmDecorator : IAlgorithm
{
private readonly IAlgorithmPool pool;
private IAlgorithm real;
public PooledAlgorithmDecorator(IAlgorithm real,
IAlgorithmPool pool)
{
this.real = real;
this.pool = pool;
}
public void Dispose()
{
if (this.real != null)
{
this.Pool.ReturnToPool(this.real);
this.real = null;
}
}
}
Now your factory can wrap the real algorithms with the decorator and return that to the consumer:
public class PooledAlgorithmFactory : IAlgorithmFactory
{
private readonly IAlgorithmPool pool;
public PooledAlgorithmFactory(IAlgorithmPool pool)
{
this.pool = pool;
}
public IAlgorithm CreateNew(string type)
{
var instance = this.pool.GetInstanceOrCreateNew(type);
return new PooledAlgorithmDecorator(instance, this.pool);
}
}
This is of course just an example. Your design will probably be different. Depending on the container you choose, you might get support for factories, object pooling and what not. I think it is important to find the correct design first and the next step is to see whether your container might be able to help you with this.