Reputation: 631
Is there any significant benefit to using either technique? In case there are variations, the Visitor Pattern I mean is this: http://en.wikipedia.org/wiki/Visitor_pattern
And below is an example of using a delegate to achieve the same effect (at least I think it is the same)
Say there is a collection of nested elements: Schools contain Departments which contain Students
Instead of using the Visitor pattern to perform something on each collection item, why not use a simple callback (Action delegate in C#)
Say something like this
class Department
{
List Students;
}
class School
{
List Departments;
VisitStudents(Action<Student> actionDelegate)
{
foreach(var dep in this.Departments)
{
foreach(var stu in dep.Students)
{
actionDelegate(stu);
}
}
}
}
School A = new School();
...//populate collections
A.Visit((student)=> { ...Do Something with student... });
*EDIT Example with delegate accepting multiple params
Say I wanted to pass both the student and department, I could modify the Action definition like so: Action
class School
{
List Departments;
VisitStudents(Action<Student, Department> actionDelegate, Action<Department> d2)
{
foreach(var dep in this.Departments)
{
d2(dep); //This performs a different process.
//Using Visitor pattern would avoid having to keep adding new delegates.
//This looks like the main benefit so far
foreach(var stu in dep.Students)
{
actionDelegate(stu, dep);
}
}
}
}
Upvotes: 5
Views: 2095
Reputation: 144226
The visitor pattern is more useful when a node in a nested structure such as a tree doesn't know the concrete type of its children. The visitor is then used to dispatch behaviour based on the real type of each child object.
In your example, the school does know that it has a child Departments
collection which in turn have child Student
collections.
If you extended your example to include another child element of School
then your code might look like:
public abstract class Manageable
{
abstract void Accept(IManagebleVisitor visitor);
}
public interface IManageableVisitor
{
void Visit(Department d);
void Visit(Building b);
}
public class Department : Manageable { ... }
public class Building : Manageable { ... }
Now your School
class might look like:
public class School
{
private List<Manageable> manageables;
public void Accept(IManageableVisitor visitor)
{
foreach(var m in this.manageables)
{
m.Accept(visitor);
}
}
}
The delegate approach doesn't work here since you'd need to pass a delegate for each concrete subclass of Manageable
, so adding any new subclasses to the hierarchy will require a change to the School.Accpet
method.
Upvotes: 4
Reputation: 217411
The visitor pattern is usually used when there are more than one type of things that are visited. You have only one type (Student
s), so you don't really need the visitor pattern and can just pass in a delegate instance.
Assume you'd want to visit both Department
s and Student
s. Then you visitor would look like this:
interface ISchoolVisitor
{
void Visit(Department department);
void Visit(Student student);
}
Of course, you could also use delegates here as well, but it would be cumbersome to pass in multiple delegate instances -- in particular if you have more than 2 types of visited things.
Upvotes: 9