2010年4月15日 星期四

Design Pattern : 13 Visitor

如果我們需要對一個複雜系統架構(Acceptor),針對整個系統做一巡訪
並做不同的動作處理,將把這處理器(Visitor)的部份獨立出來成為物件
也就是將資料處理由資料結構中分離出來,就是Visitor Pattern

例如,你有一個檔案架構系統,你希望把整個檔案目錄架構整個列印出來
我們需要有一個print_Visitor是負責來做把檔案列印出來的工作,
只要把這print_Visitor丟到一個複雜架構(acceptor)內,就會達到這目的

如果我們希望在這檔案架構內,希望可以把所有圖檔都可以產生一個縮圖
這時候,你可以產生另一個thumb_Visitor,用來負責產生縮圖的工作
只要把這thumb_Visitor丟到架構內,就會達到目的

對於一個複雜架構的系統(Acceptor),丟進去不同功能的Visitor
就可以對整個系統做不同功能的事

實作Visitor Pattern會用到一個比較複雜的遞迴(Double dispatch)
一般遞迴是自己呼叫自己,在這裡面是Acceptor與Visitor的彼此呼叫遞迴


參與者
1.Acceptor
Acceptor內需要定義一個accept method,這method只是都固定用來
把自己當作參數,呼叫啟動visitor的巡訪動作

public Class Acceptor {
     public void accept(Visitor v){
   v.visit(this)
     };
     .....
}

2.Visitor
程式的運作核心是在Visitor的visit function

public Class Visitor{
 public void visit(Acceptor entry){ 
  Iterator it=entry.iterator()
  while(it.hasNext()){
   Acceptor en=it.next();
   en.accept(this);
  }
 }
}

3.Main
外部程式

Acceptor rootdir=new Acceptor("root");
rootdir.accept(new Visitor());
4.在Visitor實作迴圈上

private String currentdir=""
public void visit(Directory dir){
 String savedir=currentdir+"/"+dir.getName()
 Iterator it=dir.iterator();
 while(it.hasNext()){
  Entry entry=(Entry)it.next();
  entry.accept(this)
 }
 currentdir=savedir;
}

在這範例內,先以一個currentdir儲存目前所在的目錄名稱
savedir會是下一層的entry所在的目錄名稱
所以在while迴圈內,利用it.next()取到的entry是與目前entry同層級的物件
entry.accept(this)裡 的this內的currentdir與現在所在的相同
while迴圈處裡完,也就是同層級的都處裡完了

currentdir=savedir是設定好,下一層級所在的目錄
下一個層級的this取到currentdir就會是目前層級得savedir

1 則留言:

匿名 提到...

last few days our class held a similar discussion about this topic and you point out something we haven't covered yet, appreciate that.

- Laura