posts - 262,  comments - 221,  trackbacks - 0
          一、Visitor模式定義:

          作用于某個(gè)對(duì)象群中各個(gè)對(duì)象的操作. 它可以使你在不改變這些對(duì)象本身的情況下,定義作用于這些對(duì)象的新操作.在Java中,Visitor模式實(shí)際上是分離了collection結(jié)構(gòu)中的元素和對(duì)這些元素進(jìn)行操作的行為.

          二、Visitor模式構(gòu)成:

          Visitor模式由被訪問(wèn)者(Visitable)和訪問(wèn)者(Visitor)構(gòu)成,兩者之間是互動(dòng)的關(guān)系,即雙方必須提供接口供彼此訪問(wèn)。下面是Visitor模式的一個(gè)例子(參考自www.jdon.com)

          ·被訪問(wèn)者接口
          public interface Visitable {

             
          public void accept(Visitor visitor);
          }


          ·被訪問(wèn)者接口實(shí)現(xiàn)類(lèi)

          public class StringElement implements Visitable {
             
          private String value;

             
          public StringElement(String string) {
                value 
          = string;
             }


             
          public String getValue(){
                
          return value;
             }


             
          // 定義accept的具體內(nèi)容 這里是很簡(jiǎn)單的一句調(diào)用
             public void accept(Visitor visitor) {
                visitor.visitString(
          this);  // 被訪問(wèn)者接受了一個(gè)訪問(wèn)者,把自己作為回調(diào)方法中的參數(shù)
             }

          }

          ·訪問(wèn)者接口
          public interface Visitor {
             
          public void visitString(StringElement stringE);
             
          public void visitFloat(FloatElement floatE);     
             
          public void visitCollection(Collection collection); 
          }


          注:因?yàn)檫@里被訪問(wèn)對(duì)象的類(lèi)型已經(jīng)明確,所以方法的形參定義可以具體到接口實(shí)現(xiàn)類(lèi),而不需要用接口類(lèi)型

          ·訪問(wèn)者接口實(shí)現(xiàn)類(lèi)
          public class ConcreteVisitor implements Visitor {
             
          // 在本方法中,我們實(shí)現(xiàn)了對(duì)Collection的元素的成功訪問(wèn)
             public void visitCollection(Collection collection) {
                Iterator iterator 
          = collection.iterator()
                
          while (iterator.hasNext()) {
                   Object o 
          = iterator.next();
                   
          if (o instanceof Visitable)       
                      ((Visitable)o).accept(
          this);
                }
           
             }


             
          public void visitString(StringElement stringE) {
                System.out.println(
          "'"+stringE.getValue()+"'");
             }
           

             
          public void visitFloat(FloatElement floatE){
                System.out.println(floatE.getValue().toString()
          +"f");
             }
           
          }

          ·客戶端調(diào)用代碼
          Visitor visitor = new ConcreteVisitor();

          StringElement stringE 
          = new StringElement("I am a String");
          visitor.visitString(stringE);

          Collection list 
          = new ArrayList();
          list.add(
          new StringElement("I am a String1")); 
          list.add(
          new StringElement("I am a String2")); 
          list.add(
          new FloatElement(new Float(12))); 
          list.add(
          new StringElement("I am a String3")); 
          visitor.visitCollection(list);

          作為Visitor模式中的被訪問(wèn)者,通常都需要定義一個(gè)setXxx和getXxx方法,為訪問(wèn)者訪問(wèn)時(shí)提供接口。或者像上例一樣,采用Call-back機(jī)制。而訪問(wèn)者也需要提供相應(yīng)的接口來(lái)接收被訪問(wèn)者,以輸出其內(nèi)容。

          三、Visitor模式的優(yōu)缺點(diǎn)

          從這個(gè)例子就可以看出Visitor模式的一個(gè)缺點(diǎn):對(duì)于集合中的所有類(lèi)型元素,訪問(wèn)者必須窮舉所有的可能方法,一旦元素的類(lèi)型比較多,則訪問(wèn)者的類(lèi)將顯得比較龐大。

          StringElement只是一個(gè)實(shí)現(xiàn),可以拓展為更多的實(shí)現(xiàn),整個(gè)核心奧妙在accept方法中,在遍歷Collection時(shí),通過(guò)相應(yīng)的accept方法調(diào)用具體類(lèi)型的被訪問(wèn)者。這一步確定了被訪問(wèn)者類(lèi)型。

          Visitor模式的一個(gè)優(yōu)點(diǎn)體現(xiàn)在對(duì)集合元素的訪問(wèn)中:由于集合中的可訪問(wèn)元素都實(shí)現(xiàn)了Visitable接口,所以在迭代集合的過(guò)程中,我們可以將每個(gè)元素都看成是接口類(lèi)型。
           
          其次由于JAVA語(yǔ)言的多態(tài)性,雖然每個(gè)元素都是接口類(lèi)型(Visitable),但每個(gè)元素的實(shí)現(xiàn)類(lèi)不同,所以在調(diào)用accept方法時(shí),虛擬機(jī)“知道”應(yīng)該調(diào)起那個(gè)正確的方法(例如:集合中的一個(gè)String元素,會(huì)調(diào)用StringElement的accept方法)

          Visitor對(duì)集合類(lèi)型的訪問(wèn)過(guò)程:對(duì)集合進(jìn)行迭代,將自身作為參數(shù)調(diào)用每個(gè)被訪問(wèn)者的accept方法,被訪問(wèn)者的accept方法也以自身為參數(shù)回調(diào)訪問(wèn)者的visitXxx方法。

          四、Visitor模式的使用前提和注意點(diǎn)

          使用訪問(wèn)者模式前提是對(duì)象群結(jié)構(gòu)中(Collection) 中的對(duì)象類(lèi)型很少改變。

          在兩個(gè)接口Visitor和Visitable中,確保Visitable很少變化,也就是說(shuō),確保不能老有新的Element元素類(lèi)型加進(jìn)來(lái),可以變化的是訪問(wèn)者行為或操作,也就是Visitor的不同子類(lèi)可以有多種,這樣使用訪問(wèn)者模式最方便.

          如果對(duì)象集合中的對(duì)象集合經(jīng)常有變化, 那么不但Visitor實(shí)現(xiàn)要變化,Visistable也要增加相應(yīng)行為,GOF建議是,不如在這些對(duì)象類(lèi)中直接逐個(gè)定義操作,無(wú)需使用訪問(wèn)者設(shè)計(jì)模式。

          --摘自www.jdon.com的《Visitor模式》 一節(jié)

          原因:

          如果Visitable中元素的類(lèi)型是固定的或者很少變化的,那么即使Visitor中相應(yīng)的訪問(wèn)行為發(fā)生改變了,對(duì)Visitable也沒(méi)有影響。相反如果Visitable中元素的類(lèi)型變化頻繁,除了Visitable要增加新的類(lèi)型,Visitor也要增加相應(yīng)的visitXxx方法。所以說(shuō)使用Visitor模式的一個(gè)前提是被訪問(wèn)者的類(lèi)型很少改變



          -------------------------------------------------------------
          生活就像打牌,不是要抓一手好牌,而是要盡力打好一手爛牌。
          posted on 2008-04-15 17:38 Paul Lin 閱讀(4481) 評(píng)論(2)  編輯  收藏 所屬分類(lèi): 模式與重構(gòu)


          FeedBack:
          # re: 設(shè)計(jì)模式總結(jié)-Visitor模式
          2008-05-11 16:04 | 無(wú)羽蒼鷹
          ^^學(xué)習(xí)了  回復(fù)  更多評(píng)論
            
          # re: 設(shè)計(jì)模式總結(jié)-Visitor模式
          2009-03-06 13:07 | rrroger
          jdon這篇文章也太老了,visitor的優(yōu)缺點(diǎn)分析的都太淺薄,參考價(jià)值不大  回復(fù)  更多評(píng)論
            
          <2008年4月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(21)

          隨筆分類(lèi)

          隨筆檔案

          BlogJava熱點(diǎn)博客

          好友博客

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 丹寨县| 大埔县| 宁陕县| 建瓯市| 公主岭市| 启东市| 洪泽县| 静宁县| 都昌县| 合川市| 太白县| 临漳县| 杭锦旗| 武川县| 泰州市| 鄂尔多斯市| 永康市| 永兴县| 嘉善县| 东丰县| 寻甸| 普兰县| 方城县| 颍上县| 吉木萨尔县| 马龙县| 汉寿县| 曲周县| 咸丰县| 正镶白旗| 镇安县| 壶关县| 南雄市| 吉隆县| 图片| 云和县| 商河县| 竹山县| 昂仁县| 咸阳市| 容城县|