5

使用这两种技术有什么显着的好处吗?如果有变化,我的意思是访问者模式:http ://en.wikipedia.org/wiki/Visitor_pattern

而下面是一个使用delegate达到同样效果的例子(至少我觉得是一样的)

假设有一组嵌套元素:学校包含包含学生的部门

与其使用访问者模式对每个集合项执行某些操作,不如使用简单的回调(C# 中的操作委托)

说这样的话

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... });

*编辑示例,代表接受多个参数

假设我想通过学生和部门,我可以像这样修改动作定义:动作

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);
            }
        }
    }
}
4

2 回答 2

9

当访问不止一种类型的事物时,通常使用访问者模式。您只有一种类型(Students ),因此您实际上并不需要访问者模式,只需传入一个委托实例即可。

假设您想同时访问Departments 和Students。然后您的访客将如下所示:

interface ISchoolVisitor
{
    void Visit(Department department);
    void Visit(Student student);
}

当然,你也可以在这里使用委托,但是传递多个委托实例会很麻烦——特别是如果你有超过 2 种类型的访问对象。

于 2012-12-07T22:45:40.630 回答
4

当嵌套结构(如树)中的节点不知道其子节点的具体类型时,访问者模式更有用。然后,访问者用于根据每个子对象的真实类型来调度行为。

在您的示例中,学校确实知道它有一个子集合Departments,而该子集合又具有子集合Student

如果您将示例扩展为包含另一个子元素,School那么您的代码可能如下所示:

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 { ... }

现在您的School课程可能如下所示:

public class School
{
    private List<Manageable> manageables;
    public void Accept(IManageableVisitor visitor)
    {
        foreach(var m in this.manageables)
        {
            m.Accept(visitor);
        }
    }
}

委托方法在这里不起作用,因为您需要为 的每个具体子类传递一个委托Manageable,因此向层次结构添加任何新子类都需要更改School.Accpet方法。

于 2012-12-07T22:50:45.917 回答