How to use a factory with Dependecy Injection without resorting to using Service Locator pattern

后端 未结 3 1878
故里飘歌
故里飘歌 2021-02-06 18:17

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.

3条回答
  •  萌比男神i
    2021-02-06 19:12

    I always like to show general answers, without going to much into features of special containers. You say the following:

    1. You need consumers to ask for new instances.
    2. Instances must be returned (probably to be reused).

    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.

提交回复
热议问题