I'm working on an engine which is meant to be configurable by the user (not end user, the library user) to use different components.
For example, let's say the class Drawer
must have an ITool
, Pencil
or Brush
, and an IPattern
, Plain
or Mosaic
. Also, let's say a Brush
must have an IMaterial
of either Copper
or Wood
Let's say the effect of choosing Pencil
or Brush
is really drastically different, and the same goes for the IPattern
type. Would it be a bad idea to code the Drawer
class with Generic concepts like this :
public class Drawer<Tool, Pattern> where Tool: ITool where Pattern : IPattern { ... }
public class Brush<Material> where Material : IMaterial { ... }
One could then use that class like :
Drawer<Pen开发者_Go百科cil, Mosaic> FirstDrawer = new Drawer<Pencil, Mosaic>();
Drawer<Brush<Copper>, Mosaic> SecondDrawer = new Drawer<Brush<Copper>, Mosaic>();
I mostly used generic for collections and such and haven't really see generics used for that kind of thing. Should I?
It does not really make sense using generics unless the engine you are creating have methods with arguments or return types of the generic type. I.e. you would expect there to be a propertie and methods like
public <Material> Material { get; }
public void Draw(<Tool> pen);
(I am currently in a Java mode so please correct the C# syntax if wrong!)
From what I can tell from the example you are only using generics for the constructor of the classes. Since you are relying on the interfaces in your implementation the use of generics does not really add value.
Perhaps I am mistaken but generics is really for type safety checked at compile time and to avoid a lot of (risky) type casting.
It could work, but it depends whether it is going to be any different to passing an ITool
/ IPattern
in via the constructor. In depends partly on convenience, and partly on whether you do anything interesting with the template parameters (for example, new
them).
To be honest, the example given does not leap to mind as a good fit for generics - you can't conveniently have a set of brushes, for example (unless you have some additional abstraction - perhaps IBrush
- not shown).
The standard winforms (system.drawing.dll) does this via static properties, like Pens.Red
, Brushes.Blue
(for a basic solid brush) - maybe take some inspiration from there? or maybe not. Up to you.
In this situation I would favour composition over generics. I imagine whilst the tool will be the responsibility of the drawer, the pattern will be the responsibility of the tool.
public class Drawer
{
private ITool _tool;
public Drawer(ITool tool, IPattern pattern)
{
_tool = new Tool(pattern);
}
...
}
public class Tool : ITool
{
private IPattern _pattern;
public Tool(IPattern pattern)
{
_pattern = pattern;
}
...
}
精彩评论