Say I have a hierarchy of classes, let's use the classic Shape
examples:
abstract class Shape
Circle : Shape
Square : Shape
I have a second hierarchy of renderer classes that handle the rendering of shapes in different ways:
abstract class ShapeRenderer
HtmlShapeRenderer : ShapeRenderer
WindowsFormsShapeRenderer : ShapeRenderer
Allowing these to vary independently would traditionally involve using the Bridge pattern. Allowing the rendering actions to be extended without modifying the Shape
classes would traditionally involve the Visitor pattern.
However, both of these focus exclusively on extending the implementation side and not the abstraction side. Say I wanted to add a new Shape
, say Triangle
- I want to be able to support rendering the Triangle
as well. Since both the Visitor and the Bridge pattern rely on "flattening" the abstraction hierarchy into a set of methods, e.g.:
public abstract class ShapeRenderer
{
public abstract void RenderCircle(Circle c);
public abstract void RenderSquare(Square s);
}
The only way to extend the Shape
hierarchy is to modify the code of the base ShapeRenderer
class, which is a breaking change.
Jon, to clarify: Using the Bridge or Visitor allows clients to provide alternative rendering implementations, but requires them to know about all potential Shapes. What I'd like to be able to do is allow clients to also be able to extend the Shape
class and require them to provide a rendering implementation for their new class. This way, existing code can work with any type of Shape
, without worrying about the particulars of rendering them.
Is there a common solution to this sort of problem usable in C#?