Introducing XnaMobileUnit I decided to roll my own unit test framework for Windows Phone 7 XNA games. I have a couple of reasons why I decided to roll my own. Among them was the fact that you cannot reference regular .Net assemblies from Windows Mobile Framework. That means that referencing NUnit was out of the question. Also using some of the other libraries that can be used for Silverlight Applications didn't quite feel right for me. The framework that I have created, XnaMobileUnit, is very simple to use and provides all the necessary functionality to run unit tests. I am still working on the framework to provide a few more capabilities and features, but for the most part it is ready to use out of the box. XnaMobileUnit is open source licensed under the Apache 2.0 License and can be downloaded from http://code.google.com/p/xna-mobile-unit/ . I recommend downloading the latest source and compiling it then referencing the new DLL. Otherwise you can simply download the l
Comments
Strategy (and template) provide abstraction of an implementation. Bridge not only abstracts an implementation, but allows the abstraction and implementation to vary independently. This is especially useful to control cominatorial explosion.
For example, you might have a graphics API for a screen display, and another graphics API for a printer or plotter. We need to be able to change between GraphicsAPI and IMyDrawingApi without caring whether we're working with a plotter or a screen (avoid GraphicsAPI.DrawOnScreen() and GraphicsAPI.DrawOnPlotter().
Bridge provides this. It involves separating what was combined in a single concern into two different abstractions, each with multiple implementations. Strategy and template simply provide one abstraction over multiple implementations.
Take a look at the sample in wikipedia (http://en.wikipedia.org/wiki/Bridge_pattern). They use the same basic concept except that instead of an interface they use an abstract class.
public class DrawingBridge
{
private IMyDrawingApi _myDrawingAdapter;
public DrawingBridge(IMyDrawingApi drawingAdapter)
{
_myDrawingAdapter = drawingAdapter;
}
public void DrawCircle(int centerX, centerY, int radius)
{
_myDrawingAdapter.DrawCircle(centerX, centerY, radius);
}
...Same for Rectangle
}
public class Display {
void DrawPixel(int x, int y, int rgbColor);
}
/* Note we're already using strategy pattern to abstract drawing on screen */
public interface Drawing
{
void DrawLine(Point topLeft, Point topRight);
}
public class SlowAndQualityDrawing : Drawing {
void DrawLine(Point topLeft, Point bottomRight)
{ /* Use Display.DrawPixel to draw simple line */ }
}
public class FastAndDraftDrawing : Drawing {
void DrawLine(Point topLeft, Point bottomRight)
{ /* Use Display.DrawPixel to draw antialiased line */ }
}
/* Now, we need to support plotters in addition to screen displays. In order to avoid four drawing methods
(SlowAndQualityDisplay, SlowAndQualityPlotter, FastAndDraftDisplay, SlowAndQualityPlotter) we need to decouple the medium from the display quality. Now we have TWO abstractions - quality and the media being rendered on. Enter the bridge between media and drawing... */
public interface Media {
void MarkSpot(int x, int y, int rgbColor);
}
public class Display : Media {
void MarkSpot(int x, int y, int rgbColor) {
/* draw a pixel */ }
}
public class Plotter : Media {
void MarkSpot(int x, int y, int rgbColor) {
/* move plotter to spot, lower head to mark paper */ }
}
public class SlowAndQualityDrawing : Drawing {
void DrawLine(Point topLeft, Point topRight)
{ /* Use Media.MarkSpot to draw simple line */ }
}
public class FastAndDraftDrawing : Drawing
{
void DrawLine(Point topLeft, Point bottomRight)
{ /* Use Media.MarkSpot to draw antialiased line */ }
}
/* There is no standalone "bridge" object, rather the bridge is between the drawing implementations
and the media implementations. We've made a bridge by splitting out responsibility for an aspect
of drawing into a second abstraction. Now the Media and Drawing implementations can vary without
effecting each other. Note we still have only two drawing methods, instead of the four we'd end up
with if we didn't create the media-drawing bridge. */
Also I think that patterns can differ in implementation. As long as they are serving their purpose, then they have met their goal.
I completely agree with you. I expanded the example simply to illustrate a more concrete sense (media and quality) of two differing concerns being bridged by separating them into two different abstractions.
One of the problems with patterns is struggling with slightly differing implementations being classified differently by different people. They're still very much worth studying and discussing though.