Friday, 1 June 2012

Simulate MultiMethods with the Visitor Pattern

There are some Design Patterns that become part of your everyday life, there are others that you rarely use and keep fading somewhere in your mind. One friend of mine mentioned the other day having being questioned about the Visitor Pattern when doing a job interview. That made me think a bit about its use and implementation, and then I recalled that apart from its typical use when building compilers, part of the reason for this pattern is simulating MultiMethods (Dynamic Dispatch). It pretty much called my attention that the entry in Wikipedia does mention this, but does not include a sample, which prompted me to write my own.

Sure there are millions of much better samples one google search away, but hey, I feel like sharing it anyway

public abstract class Person //item to be visited
{
 public string Name{get;set;}
 
 public abstract bool TryToEnter(Party party); //Accept
}

public class Employer: Person
{
 public override bool TryToEnter(Party party)
 {
  return party.Admit(this);
 }
}

public class Employee: Person
{
 public override bool TryToEnter(Party party)
 {
  return party.Admit(this);
 }
}

//visitor
public class Party 
{
 //Visit method
 public bool Admit(Employer e) 
 {
  return true;
 }
 
 public bool Admit(Employee e)
 {
  return false;
 }
}

public class App
{
 public static void Main()
 {
  var party = new Party();
  var persons = new List<Person>()
  {
   new Employer(){Name="Xuan"},
   new Employee(){Name="Xose"}
  };
  
  foreach(Person p in persons)
  {
   if (p.TryToEnter(party))
    Console.WriteLine(p.Name + " entered the party");
   else
    Console.WriteLine(p.Name + " DID NOT enter the party");
  }
 }
}

I have to say that this technique for simulating MultipleDispatch seems terribly artificial to me. The Accept method (TryToEnter in this case) that you have to add to the element on which you want to base your dispatch, appears like an ugly hack, cause it has nothing to do with the semantics of the (Person) class. Indeed, we've had to alter our thinking, with multimethod support we would just call to Party.Admit, and not the other way around as we're doing now with Person.TryToEnter.
Anyway, you can grab the code here

No comments:

Post a Comment