How do I let the user of class X choose the implementation of the interface that class X uses?
I have a design question. I have a CodesTree class that builds a kind of binary tree according to the data provided, and the algorithm used needs a priority queue (nota bene is also implemented using a binary tree). There may be different implementations of the priority queue, so I would like to allow the user of my class to choose the implementation they prefer. I designed the queue interface as follows:
public interface IPriorityQueue<T>
{
T GetMax();
void Insert(T value);
int Count { get; }
}
The question is, how can I let the user choose the implementation? The only way I can think of is to make a public property of type IPriorityQueue in my CodesTree class and let the user set that property to the instance of the class they want to use. But I don't think this is a good idea, because the user can specify a queue that, for example, already has several elements, or, having a reference to the queue, removes some elements (and he shouldn't). Itβs just a little subtle. What's the best way?
a source to share
FROM#
Limit the passed type IPriorityQueue<>
to new()
-able types and make the item local. This reduces your options, but is the safest way. The user will have to go through a malicious implementation IPriorityQueue<>
.
public class CodesTree<T>
where T: IPriorityQueue<Codes>, new()
{
public CodesTree()
{
_queue = new T();
}
// ...
}
Runtime
If you cannot or will not create the queue yourself, you can always explicitly check the requirements in the constructor:
public CodesTree(IPriorityQueue<Codes> queue)
{
if (queue == null || queue.Count > 0)
throw new ArgumentException("queue");
_queue = queue;
}
This method is much more flexible because it allows arbitrarily constructed queues, but can lead to unexpected exceptions at runtime.
Checking the queue at runtime also allows you all the DI / IoC goodness that others recommend in this matter.
a source to share
What you are looking for is called dependency injection . You can either pass an instance of the implementation in the constructor, or you can use the dependency injection framework there to handle this.
a source to share
Pass the factory priority queue to the constructor CodesTree
.
public interface IPriorityQueueFactory<T>
{
IPriorityQueue<T> CreatePriorityQueue();
}
Then IPriorityQueueFactory<T>
passed to the constructor.
This project uses Factory Pattern and Parameterize from above figure .
a source to share
One way I can think of is using the default template, and if the user wants to use a different priority queue, he can:
template < typename T, typename C = default_priority_queue<T>>
class CodesTree {};
Edit: I didn't realize we were in C #.
Try:
class CodesTree<T,C> where C : IPriorityQueue<T> {
}
I don't know if C might be the default, tho.
a source to share
Your solution (the public property IPriorityQueue) is usually seen using Dependency Injection (or Inversion of Control) frameworks and is called "setter injection".
Another option would be Constructor Injection, where the implementation of the interface is provided as a parameter to the constructor.
There are many of these frameworks to choose from: .Net has Unity, Spring.Net, StructureMap Castle Windsor and others. Java has Spring and maybe others.
These frameworks allow the user to specify the implementation they want to use in the XML configuration file, or by providing the configuration at runtime to the Dependency Injection container.
When objects are instantiated using such a structure, it takes care of creating / retrieving the dependency and providing them with the dependent object.
a source to share