2012-12-07 26 views
3

使用這兩種技術有什麼重大的好處嗎?萬一有變型中,訪問者模式我的意思是這樣的:http://en.wikipedia.org/wiki/Visitor_patternVisitor Pattern可以用回調函數替換嗎?

而下面是使用委託來達到同樣的效果(至少我認爲它是一致的)

說有的一個例子嵌套元素的集合:學校都包含有學生

而不是使用訪問者模式來執行每個收集項目什麼部門,爲什麼不使用一個簡單的回調(在C#Action委託)

說這句話

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

*與委託接收多種PARAMS

說我想通過學生和部門都EDIT例如,我可以修改的操作定義,像這樣: 行動

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); 
      } 
     } 
    } 
} 
+1

我覺得這種風格很吸引人。儘管如此,有些人會爭先恐後地堅持自己的語法重型設計模式。 – ChaosPandion

回答

8

訪問者模式通常用於存在多個訪問過的事物時。你只有一種類型(Student s),所以你不需要訪問者模式,只需傳入一個委託實例即可。

假設您想要同時訪問Department s和Student s。然後,你的來訪者是這樣的:

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

當然,你也可以在這裏使用委託爲好,但它會很麻煩在多個委託實例傳遞 - 特別是如果你有超過2種訪問過的東西

+0

謝謝,這很有道理,我已經用多個代表的另一個例子更新了我的帖子 – getit

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方法。

+0

樹節點如何不知道他們的子類型?所有的節點是否會從一個通用接口繼承,然後訪問者會以某種方式確定它(使用運行時類型標識可能) – getit

+0

非常好,謝謝你的例子 – getit

相關問題