December 19, 2004
Revisiting the Visitor pattern
The visitor pattern is a very useful technique. I intend to use it for implementing the various passes over the C# abstract syntax tree (AST) that my C# to C++ translator will need to make.
One of the key benefits of the visitor pattern is that it gives you the effect of injecting new virtual functions into a class hierarchy without actually having to modify those classes. The big win for me is I will need to make only minimal changes to the C# compiler code, which will make it easy for me to merge in future versions of the code when they become available.
This article addresses some issues with the visitor pattern.
It occurred to me that by using the new features of C# 2.0, I can do a little better than the improved visitor pattern proposed in this article. Following the Don't Repeat Yourself principle, I can use C# generics to eliminate some of the redundancy.
Compare this example code to that in the aforementioned article. The individual multiply-inherited visitor base classes for specific kinds of modem are replaced by a single generic interface. The Accept methods in each modem class are simplified with most of the logic moving into the generic Dispatch method of the base class.
Sorry about the code formatting. I'm having to type it in by hand as HTML. There must be an easier way!
One of the key benefits of the visitor pattern is that it gives you the effect of injecting new virtual functions into a class hierarchy without actually having to modify those classes. The big win for me is I will need to make only minimal changes to the C# compiler code, which will make it easy for me to merge in future versions of the code when they become available.
This article addresses some issues with the visitor pattern.
It occurred to me that by using the new features of C# 2.0, I can do a little better than the improved visitor pattern proposed in this article. Following the Don't Repeat Yourself principle, I can use C# generics to eliminate some of the redundancy.
Compare this example code to that in the aforementioned article. The individual multiply-inherited visitor base classes for specific kinds of modem are replaced by a single generic interface. The Accept methods in each modem class are simplified with most of the logic moving into the generic Dispatch method of the base class.
Sorry about the code formatting. I'm having to type it in by hand as HTML. There must be an easier way!
public abstract class Modem
{
public abstract void Accept(object visitor);
protected static void Dispatch<M>(M modem, object visitor) where M : Modem
{
IModemVisitor<M> iface = visitor as IModemVisitor<M>;
if (iface != null)
{
iface.Visit(modem);
}
else
{
// throw exception or do nothing as appropriate
}
}
}
public class HayesModem : Modem
{
public override void Accept(object visitor) { Dispatch(this, visitor); }
}
public class ZoomModem : Modem
{
public override void Accept(object visitor) { Dispatch(this, visitor); }
}
public interface IModemVisitor<M> where M : Modem
{
void Visit(M modem);
}
public class ConfigureDOSModemVisitor:
IModemVisitor<HayesModem>,
IModemVisitor<ZoomModem>
{
public void Visit(HayesModem modem)
{ }
public void Visit(ZoomModem modem)
{ }
}