Learning WPF with BabySmash - Factories, Interfaces, Delegates and Lambdas, oh my!
NOTE: If you haven't read the first post in this series, I would encourage you do to that first, or check out the BabySmash category. Also check out http://windowsclient.net/ for more developer info on WPF.
BACKGROUND: This is one of a series of posts on learning WPF. I wrote an application for my 2 year old using WPF, but as I'm a Win32-minded programmer, my working app is full of Win32-isms. It's not a good example of a WPF application even though it uses the technology. I'm calling on community (that's you, Dear Reader) to blog about your solutions to different (horrible) selections of my code. You can get the code http://www.codeplex.com/babysmash. Post your solutions on your blog, in the comments, or in the Issue Tracker and we'll all learn WPF together. Pick a single line, a section, or subsystem or the whole app!
BabySmash has a little mini-hierarchy of "Figures" that represent the Shapes on the screen. There is a "FigureGenerator" that is meant to return a random Figure whenever the baby hits a key.
I thought it would be interesting to walk through the several different ways one could solve this problem, depending on what version of the .NET Framework one has available. This isn't an exhaustive list, of course, and I'm VERY interested in your refactorings, Dear Reader, so leave them in the comments inside <pre> tags. Thanks to Scott Cate (and his son) for his help with this post today.
Original Yucky Random Factory
What's the catch? Well, here's one. The "FigureGenerator" looks like this currently. I know it sucks because of all the TODOs. If that isn't enough of a hint for you, the switch statement is your 9th hint. This is actually pretty common WTF code that you've likely seen in the wild. Perhaps you'd even admit to writing something like it yourself.
private static Figure GenerateFigure(string letter)
{
//TODO: Should this be in XAML? Would that make it better?
Brush fill = Utils.GetRandomColoredBrush();
if (letter.Length == 1 && Char.IsLetterOrDigit(letter[0]))
{
return new LetterFigure(fill, letter);
}
int shape = Utils.RandomBetweenTwoNumbers(0, 6);
//TODO: Should I change the height, width and stroke to be relative to the screen size?
//TODO: I think I need a shapefactory?
//TODO: Where can I get REALLY complex shapes like animal vectors or custom pics? Where do I store them?
switch (shape)
{
case 0:
return new SquareFigure(fill);
case 1:
return new CircleFigure(fill);
case 2:
return new TriangleFigure(fill);
case 3:
return new StarFigure(fill);
case 4:
return new HeartFigure(fill);
case 5:
return new TrapezoidFigure(fill);
case 6:
return new RectangleFigure(fill);
}
return null;
}
Why so gross? Well, the goal here is to be an object factory, but to be a random object factory that returns any of a list of Figures. Notice, though, that a Letter is a special kind of Figure depending on what key the baby pressed. It's still a figure, except it's the only one that cares what key was pressed.
What I need is a better Factory to make these Figures, but a "random factory" that is a little easier to extend than a Switch statement.
Random List of Factories with Interfaces - The 1.1 Way
I'm trying to create a RandomFactory that makes concrete instances of random Shapes that drive from an abstract class. Its the randomness that's important, so I need to randomly select from a list of potentials.
On the reflection side of things, I could have created an array of System.Types then randomly picked one, then used Reflection via Activator.CreateInstance to create something concrete. However, Reflection should be a last resort, and this isn't that complex of a pattern.
One oldish, simple solution would be to create an array of FigureFactories like this:
interface IFigureFactory
{
Figure CreateFigure(Brush fill);
}
public class StarFigureFactory : IFigureFactory
{
public Figure CreateFigure(Brush fill)
{
return new StarFigure(fill);
}
}
public class SquareFigureFactory : IFigureFactory
{
public Figure CreateFigure(Brush fill)
{
return new SquareFigure(fill);
}
}
I'd need to make an array of these, then pick one randomly:
IFigureFactory[] figfacts = new IFigureFactory[]
{
new StarFigureFactory(),
new SquareFigureFactory()
//etc...
};
IFigureFactory figfac = Utils.RandomBetweenTwoNumbers(0, figfacts.Length);
Figure f = figfac.CreateFigure(fill);
This works pretty well, but requires all those FigureFactories.
Random List of Factories with Generics - The 2.0 Second Way Attempt
But, if I was using .NET 2.0, I might say, "hey, what about generics?" I could start creating a GenericFigureFactory<T> to try and get rid of all those other custom tiny factories.
public class GenericFigureFactory<T> where T : Figure, new()
{
public Figure CreateFigure(Brush fill)
{
Figure f = new T(fill);
//Cannot provide arguments when creating instance of T
}
}
However, it's not so clean because even though the system KNOWS that T is of type Figure and that Figure has a constructor that takes a Brush, I can't call that constructor. At this point, I'd need to set properties instead of a constructor with a parameter. Poop. FAIL.
Random Factories with Delegates - The 2.0 Way
Perhaps this is too much work, with the generics and the interfaces. All I really need is a bunch of methods where the signature is "take a Brush, return a Figure." Some kind of delegate that had that signature. ;)
public delegate Figure FigureFactory<Brush, Figure>(Brush x);
So that's 2.0 style delegate that takes a Brush and returns a Factory. Remember that a delegate in this example an exemplar. It's an example of what a method should look like. It's not the method itself, just the meta-method.
I can make a list of these factories, defining the body as I add them. Then, grab a random one and call it.
List<FigureFactory<Brush, Figure>> foo = new List<FigureFactory<Brush, Figure>>();
foo.Add(delegate(Brush x) { return new SquareFigure(x); });
foo.Add(delegate(Brush x) { return new StarFigure(x); });
FigureFactorymyFunc = foo[Utils.RandomBetweenTwoNumbers(0, foo.Count-1)];
Figure f = myFunc(fill);
That delegate up there that takes something and returns something could be made generic, like this:
public delegate TResult Func<TParam, TResult>(TParam p);
That's SO useful that it was added in .NET 3.5 as System.Func and it lives in System.Core.dll. If you want this kind of functionality in .NET 2.0, then just define your own bunch of Funcs. I got this tip from Scott Cate. Remember, if you're using .NET 3.5, you don't need these, they already exist.
public delegate void Func<T>();
public delegate TRes Func<TSrc1, TRes>(TSrc1 src1);
public delegate TRes Func<TSrc1, TSrc2, TRes>(TSrc1 src1, TSrc2 src2);
public delegate TRes Func<TSrc1, TSrc2, TSrc3, TRes>(TSrc1 src1, TSrc2 src2, TSrc3 src3);
public delegate TRes Func<TSrc1, TSrc2, TSrc3, TSrc4, TRes>(TSrc1 src1, TSrc2 src2, TSrc3 src3, TSrc4 s
Still, this could be cleaner.
Random Factories with Lambdas - The 3.5 Way
"At first glance, lambda methods look like nothing more than a syntactic sugar, a more compact and pleasant syntax for embedding an anonymous method in code."
There are some subtle differences, and if you want to learn more I encourage you to check out Part 1, Part 2, Part 3, Part 4 and Part 5 of his detailed series on just those differences. For what we're doing, all that matters is that lambdas are nicer to look at.
Now, replacing the delegates with lambdas changes the delegate way:
List<FigureFactory<Brush, Figure>> foo = new List<FigureFactory<Brush, Figure>>();
foo.Add(delegate(Brush x) { return new SquareFigure(x); }); //etc...
to
var foo = new List
{
x => new SquareFigure(x), //etc...
}
So the whole random generator cleans up to just this chunk of code, with the list of figures moved out to a private field:
private static readonly List<Func<Brush, Figure>> listOfPotentialFigures =
new List<Func<Brush, Figure>>
{
x => new SquareFigure(x),
x => new CircleFigure(x),
x => new TriangleFigure(x),
x => new StarFigure(x),
x => new HeartFigure(x),
x => new TrapezoidFigure(x),
x => new RectangleFigure(x)
};
private static Figure GenerateFigure(string letter)
{
var fill = Utils.GetRandomColoredBrush();
if (letter.Length == 1 && Char.IsLetterOrDigit(letter[0]))
return new LetterFigure(fill, letter);
var myFunc = listOfPotentialFigures[
Utils.RandomBetweenTwoNumbers(0, listOfPotentialFigures.Count-1)];
return myFunc(fill);
}
This feels MUCH cleaner than switch statement and it's easy to extend with a single line and it exactly expresses what I intend to do. In the future I may look at using an IOC (Inversion of Control) container to add figures dynamically via plugin or discovery model.
I'm interested in your comments as there's very likely an even cleaner pattern to solve this little problem in your head, waiting to get out.
About Scott
Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.
About Newsletter

NOTE: If you haven't read the
I've been getting more and more interested in how folks extend their applications using plugins and things. In my new ongoing quest to read source code to be a better developer, Dear Reader, I present to you twenty-eighth in a infinite number of posts of "The Weekly Source Code."