I have a StaffFactory for getting Staff objects by various means, but I also have some setup methods to determine which data source to use.
class StaffFactory
{
private const string DefaultDbSourceName = "Production";
private string dbSourceName;
#region Factory Management
private static Dictionary<string, StaffFactory> staffFactories = new Dictionary<string,StaffFactory>();
public static StaffFactory GetInstance()
{
return GetInstance(DefaultDbSourceName);
}
public static StaffFactory GetInstance(string dbSourceName)
{
if (!staffFactories.ContainsKey(dbSourceName))
{
staffFactories.Add(dbSourceName, new StaffFactory(dbSourceName));
}
return staffFactories[dbSourceName];
}
private StaffFactory(string dbSourceName)
{
this.dbSourceName = dbSourceName;
}
#endregion Factory Management
#region Factory Methods
public Staff ById(int id) { ... }
public IList<Staff> ByName(string name) { ... }
...
#endregion Factory Methods
}
As I go to create my next factory, I realise all this management logic is going to remain the same regardless of what type the factory is for. So I'm thinking I create some base Factory or Factory class that houses that logic, and then my declare the above with class StaffFactory : Factory<Staff> { ... }
or something, but I'm drawing complete blanks on how I would go about that. Whether or not to implement it using generics, etc.
Can anyone point me in the right direction?
Before you introduce a new abstraction layer, make sure that the benefits will outweigh the costs. In your case, those would include:
The cost to design and implement the abstraction
StaffFactory is much easier to design, implement and test than a generic Factory<T> class.
The cost to understand the Factory<T> abstraction
Every time someone reads the code, they may need to wrap their head around the abstraction. A generic abstraction is harder to wrap your head around than a non-generic one.
The cost to make changes in the future
Let's say that you have Factory<Staff> and Factory<Product>, and in the future you find that you want a different caching policy for the two. Maybe the Factory<Product> should discard the cached object if the cache size exceeds some threshold.
Are you going to generalize the Factory<> class to support different modes? That can be done, but its much more complex than just modifying StaffFactory and ProductFactory classes independently.
Summary
So, don't introduce an abstraction just for the sake of it. And, definitely do not generalize StaffFactory into a generic Factory<T> if Factory<Staff> is going to be the only generic instantiation you'll have.
From your code above, it seems that your Factory<T> class would be basically a Dictionary<string, T>. If that's the case, then introducing the additional generic Factory class does not get you much benefit and only adds an unnecessary abstraction layer.