亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

用Reflection實現Visitor模式

2019-11-18 12:17:23
字體:
來源:轉載
供稿:網友

  Visitor模式的常用之處在于,它將對象集合的結構和對集合所執行的操作分離開來。例如,它可以將一個編譯器中的分析邏輯和代碼生成邏輯分離開來。有了這樣的分離,想使用不同的代碼生成器就會很輕易。更大的好處還有,其它一些公用程序,如lint,可以在使用分析邏輯的同時免受代碼生成邏輯之累。不幸的是,向集合中增加新的對象往往需要修改已經寫好的Visitor類。本文提出了一種在java中實現Visitor模式的更靈活的方法:使用Reflection(反射)。
  
  集合(Collection)普遍應用于面向對象編程中,但它也經常引發一些和代碼有關的疑問。例如,"假如一個集合存在不同的對象,該如何對它執行操作?"
  
  一種方法是,對集合中的每個元素進行迭代,然后基于所在的類,對每個元素分別執行對應的操作。這會很難辦,非凡是,假如你不知道集合中有什么類型的對象。例如,假設想打印集合中的元素,你可以寫出如下的一個方法(method):
  
  public void messyPRintCollection(Collection collection) {
  Iterator iterator = collection.iterator()
  while (iterator.hasNext())
   System.out.println(iterator.next().toString())
  }
  
  這看起來夠簡單的了。它只不過調用了Object.toString()方法,然后打印出對象,對嗎?但假如有一組哈希表怎么辦?事情就會開始變得復雜起來。你必須檢查從集合中返回的對象的類型:
  
  public void messyPrintCollection(Collection collection) {
  Iterator iterator = collection.iterator()
  while (iterator.hasNext()) {
   Object o = iterator.next();
   if (o instanceof Collection)
   messyPrintCollection((Collection)o);
   else
   System.out.println(o.toString());
  }
  }
  
  不錯,現在已經解決了嵌套集合的問題,但它需要對象返回String,假如有其它不返回String的對象存在怎么辦?假如想在String對象前后添加引號以及在Float后添加f又該怎么辦?代碼還是越來越復雜:
  
  public void messyPrintCollection(Collection collection) {
  Iterator iterator = collection.iterator()
  while (iterator.hasNext()) {
   Object o = iterator.next();
   if (o instanceof Collection)
   messyPrintCollection((Collection)o);
   else if (o instanceof String)
   System.out.println("""+o.toString()+""");
   else if (o instanceof Float)
   System.out.println(o.toString()+"f");
   else
   System.out.println(o.toString());
  }
  }
  
  可以看到,事情的復雜度會急劇增長。你當然不想讓一段代碼到處充斥著if-else語句!那怎么避免呢?Visitor模式可以幫你。
  
  要實現Visitor模式,得為訪問者建立一個Visitor接口,還要為被訪問的集合建立一個Visitable接口。然后,讓具體類實現Visitor和Visitable接口。這兩個接口如下所示:
  
  public interface Visitor
  {
  public void visitCollection(Collection collection);
  public void visitString(String string);
  public void visitFloat(Float float);
  }
  
  public interface Visitable
  {
  public void accept(Visitor visitor);
  }
  
  對于具體的String,可能是這樣:
  
  public class VisitableString implements Visitable
  {
  private String value;
  public VisitableString(String string) {
  value = string;
  }
  public void accept(Visitor visitor) {
   visitor.visitString(this);
  }
  }
  
  在accept方法中,對this類型調用正確的visitor方法:
  
  visitor.visitString(this)
  
  這樣,就可以如下實現具體的Visitor:
  
  public class PrintVisitor implements Visitor
  {
  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(String string) {
  System.out.println("""+string+""");
  }
  
  public void visitFloat(Float float) {
  System.out.println(float.toString()+"f");
  }
  }
  
  實現VisitableFloat和VisitableCollection類的時候,它們也是各自調用合適的Visitor方法,所得到的效果和前面那個用了if-else的messyPrintCollection方法一樣,但這里的手法更干凈。在visitCollection()中,調用的是Visitable.accept(this),然后這個調用又返回去調用一個合適的Visitor方法。這被稱做 "雙分派";即,Visitor先調用了Visitable類中的方法,這個方法又回調到Visitor類中。
  
  雖然通過實現visitor消除了if-else語句,卻也增加了很多額外的代碼。最初的String和Float對象都要用實現了Visitable接口的對象進行包裝。這有點討厭,但一般說來不是問題,因為你可以讓經常被訪問的集合只包含那些實現了Visitable接口的對象。
  
  但似乎這還是額外的工作。更糟糕的是,當增加一個新的Visitable類型如VisitableInteger時,會發生什么呢?這是Visitor模式的一個重大缺陷。假如想增加一個新的Visitable對象,就必須修改Visitor接口,然后對每一個Visitor實現類中的相應的方法一一實現。你可以用一個帶缺省空操作的Visitor抽象基類來代替接口。那就很象Java GUI中的Adapter類。那個方法的問題在于,它需要占用單繼續;而你往往想保留單繼續,讓它用于其它什么東西,比如繼續StringWriter。那個方法還有限制,它只能夠成功訪問Visitable對象。
  
  幸運的是,Java可以讓Visitor模式更靈活,使得你可以隨心所欲地增加Visitable對象。怎么做?答案是,使用Reflection。比如,可以設計這樣一個ReflectiveVisitor接口,它只需要一個方法:
  
  public interface ReflectiveVisitor {
  public void visit(Object o);
  }
  
  就這樣,很簡單。至于Visitable,還是和前面一樣,我過一會兒再說。現在先用Reflection來實現PrintVisitor:
  
  public class PrintVisitor implements ReflectiveVisitor {
  public void visitCollection(Collection collection)
  { ... same as above ... }
  public void visitString(String string)
  { ... same as above ... }
  public void visitFloat(Float float)
  { ... same as above ... }
  
  public void default(Object o)
  {
   System.out.println(o.toString());
  }
  
  public void visit(Object o) {
   // Class.getName() returns package information as well.
   // This strips off the package information giving us
   // just the class name
   String methodName = o.getClass().getName();
   methodName = "visit"+
   methodName.substring(methodName.lastIndexOf(".")+1);
   // Now we try to invoke the method visit
   try {
   // Get the method visitFoo(Foo foo)
   Method m = getClass().getMethod(methodName,
   new Class[] { o.getClass() });
   // Try to invoke visitFoo(Foo foo)
   m.invoke(this, new Object[] { o });
   } catch (NoSUChMethodException e) {
   // No method, so do the default implementation
   default(o);
   }
  }
  }
  
  現在不需要Visitable包裝類。僅僅只是調用visit(),請求就會分發到正確的方法上。很不錯的一點是,只要認為適合,visit()就可以分發。這并非必須使用reflection--它可以使用其它完全不同的機制。
  
  新的PrintVisitor中,有針對Collection,String和Float而寫的方法,但然后它又在catch語句中捕捉所有未處理的類型。你要擴展visit()方法,使得它也能夠處理所有的父類。首先,得增加一個新方法,稱為getMethod(Class c),它返回的是要調用的方法;為了找到這個相匹配的方法,先在類c的所有父類中尋找,然后在類c的所有接口中尋找。
  
  protected Method getMethod(Class c) {
  Class newc = c;
  Method m = null;
  // Try the superclasses
  while (m == null && newc != Object.class) {
   String method = newc.getName();
   method = "visit" + method.substring(method.lastIndexOf(".") + 1);
   try {
   m = getClass().getMethod(method, new Class[] {newc});
   } catch (NoSuchMethodException e) {
   newc = newc.getSuperclass();
  }
  }
  // Try the interfaces. If necessary, you
  // can sort them first to define "visitable" interface wins
  // in case an object implements more than one.
  if (newc == Object.class) {
  Class[] interfaces = c.getInterfaces();
  for (int i = 0; i < interfaces.length; i++) {
   String method = interfaces[i].getName();
   method = "vis

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
最新日韩中文字幕| 国产一区二区三区视频在线观看| 91欧美精品成人综合在线观看| 国产亚洲a∨片在线观看| 欧美巨大黑人极品精男| 亚洲精品有码在线| 欧洲成人在线视频| 国产精品美乳在线观看| 欧美激情一区二区三区高清视频| 亚洲欧美日韩国产精品| 久久伊人精品天天| 91国偷自产一区二区三区的观看方式| 美女扒开尿口让男人操亚洲视频网站| 久久久精品在线观看| 久久97精品久久久久久久不卡| 亚洲黄色在线看| 91精品国产自产91精品| 亚洲第一二三四五区| 91久久综合亚洲鲁鲁五月天| 亚洲精品91美女久久久久久久| 91在线免费网站| 亚洲一区二区在线播放| 91久久精品在线| 日韩毛片中文字幕| 久久免费视频观看| 免费91在线视频| 亚洲品质视频自拍网| 91精品国产自产在线观看永久| 国产精品自产拍在线观| 国产精品福利网站| 久久噜噜噜精品国产亚洲综合| 欧美日韩国产在线播放| 精品久久久久久久久久国产| 亚洲人精品午夜在线观看| 国内外成人免费激情在线视频| 亚洲天堂色网站| 日av在线播放中文不卡| 亚洲午夜未满十八勿入免费观看全集| 国产精选久久久久久| 欧美另类暴力丝袜| 成人夜晚看av| 国产精品欧美日韩久久| 国产精品天天狠天天看| 91成人天堂久久成人| 国语自产精品视频在线看一大j8| 国a精品视频大全| 欧美性感美女h网站在线观看免费| 2023亚洲男人天堂| 色yeye香蕉凹凸一区二区av| 热re91久久精品国99热蜜臀| 欧美日韩美女在线观看| www.99久久热国产日韩欧美.com| 亚洲石原莉奈一区二区在线观看| 成人黄色中文字幕| 久久久久久尹人网香蕉| 亚洲电影免费观看| 国产成人在线视频| 欧美精品成人在线| 2021久久精品国产99国产精品| 国产视频欧美视频| 米奇精品一区二区三区在线观看| 狠狠躁夜夜躁久久躁别揉| 91成人精品网站| 日韩成人在线观看| 一本大道久久加勒比香蕉| 91精品国产高清久久久久久91| 国产精品ⅴa在线观看h| 色综久久综合桃花网| 国产日韩精品一区二区| wwwwwwww亚洲| 色综合天天狠天天透天天伊人| 国产精品欧美日韩久久| 成人福利在线视频| 91av国产在线| 欧美成人一区在线| 狠狠综合久久av一区二区小说| 久久久欧美一区二区| 亚洲最大的成人网| 国产精品对白刺激| 2019中文字幕在线免费观看| 在线电影av不卡网址| 伊人亚洲福利一区二区三区| 欧美大片在线看免费观看| 日韩亚洲欧美中文高清在线| 亚洲第一网站男人都懂| 亚洲一二三在线| 92国产精品久久久久首页| 国产精品一区二区三区久久久| 日本aⅴ大伊香蕉精品视频| 国产成人精彩在线视频九色| 亚洲精品一区中文| 亚洲国产欧美自拍| 成人日韩av在线| 欧美精品电影在线| 美女999久久久精品视频| 欧美裸体xxxxx| 日韩在线视频网| 97在线免费观看| 亚洲精品久久久久久久久| 亚洲成色777777女色窝| 欧美性生活大片免费观看网址| 7777精品久久久久久| 国产精品视频自在线| 精品毛片三在线观看| 久久精品久久久久久国产 免费| 91精品啪在线观看麻豆免费| 欧美激情videos| 欧美国产精品人人做人人爱| 国产成人欧美在线观看| 91精品一区二区| 亚洲欧美日韩精品久久奇米色影视| 国产精品大陆在线观看| 国产精品网红福利| 亚洲国产毛片完整版| 日韩av在线影院| 国产精品视频一区国模私拍| 中文字幕日韩欧美在线| 国产精品第二页| 欧美一级视频免费在线观看| 中国日韩欧美久久久久久久久| 欧美亚洲成人xxx| 亚洲天堂av女优| 亚洲最新av在线网站| 亚洲人线精品午夜| 亚洲视频欧美视频| 日韩免费观看av| 欧美日韩亚洲一区二区三区| 欧美一区二粉嫩精品国产一线天| 国模私拍一区二区三区| 欧美日韩国产一区二区三区| 这里精品视频免费| 欧美猛交ⅹxxx乱大交视频| 91精品视频在线免费观看| 久久久久久91香蕉国产| 精品久久香蕉国产线看观看亚洲| 国外成人性视频| 高清一区二区三区四区五区| 欧美激情成人在线视频| 欧美精品做受xxx性少妇| 亚洲精品自拍视频| 日韩美女视频在线观看| www.久久草.com| 久久久国产成人精品| 欧美视频裸体精品| 日韩中文在线中文网在线观看| 久久久免费观看| 欧美韩日一区二区| 色噜噜亚洲精品中文字幕| 成人免费大片黄在线播放| 亚洲综合日韩中文字幕v在线| 日韩av男人的天堂| 国产精品爱啪在线线免费观看| 91精品久久久久久久久| 久久综合久中文字幕青草| 久久久黄色av| 岛国视频午夜一区免费在线观看| 亚洲第五色综合网| 亚洲国产私拍精品国模在线观看| 日韩成人在线电影网| 欧美日韩激情视频8区| 欧美一级黄色网| 国产伦精品一区二区三区精品视频| 久久精品视频播放| 亚洲国产日韩欧美综合久久|