細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks
          在Java中所有的物件都繼承自Object物件,這樣作的優點之一,就是使得一些集合物件的資料結構容易管理,例如您可以將任何型態的物件放入Vector中。

          然而現在有個問題是,如果您的集合(connection)物件中不僅儲存一種型態的物件,如果想要對這些物件作出一些個別化的操作,首要條件就是要知道該物件的型態,使用 instanceof 似乎是個不錯的方式,在程式簡單的情況下,也許您會這麼作:
           public class ElementA {
              // some implementing
           }
           
           public class ElementB {
              // some implementing
           }

           public class ElementC {
              // some implementing
           }

           // ......

              Iterator iterator = arrayList.iterator()
              while (iterator.hasNext()) {
                  if (o instanceof ElementA)
                  (ElementA) o.operationA();
                  else if (o instanceof ElementB)
                   (ElementB) o.operationB();
                else if (o instanceof ElementC)
                   (ElementC) o.operationC();
                else
                   System.out.println(
                            "Sorry! I don't know who you are! "
                             + o.toString());
                  //....
              }

              //....
           
          這麼作並不是不可以,只是將來的擴充性不大,如果今天您想要一次改變對每一種類型物件的操作,您必須修改很多地方。

          從物件自身的角度來想好了,物件在一個個的房子中,物件說:「不要在房子外費盡心思判斷了,即然您不知道我是誰,那麼您就進來訪問我好了,我告訴您我是誰,這麼一來您就知道如何操作我了!」

          用程式來實現上面這個描述:
          • IElement.java
          public interface IElement { 
          public void accept(IVisitor visitor);
          }

          • ElementA.java
          public class ElementA implements IElement { 
          public void accept(IVisitor visitor) {
          visitor.visit(this);
          }

          public void operationA() {
          System.out.println(
          "do A's job....such-and-such....");
          }
          }

          • ElementB.java
          public class ElementB implements IElement { 
          public void accept(IVisitor visitor) {
          visitor.visit(this);
          }

          public void operationB() {
          System.out.println(
          "do B's job....such-and-such....");
          }
          }

          • ElementC.java
          public class ElementC implements IElement { 
          public void accept(IVisitor visitor) {
          visitor.visit(this);
          }

          public void operationC() {
          System.out.println(
          "do C's job....such-and-such....");
          }
          }

          • IVisitor.java
          public interface IVisitor { 
          public void visit(ElementA element);
          public void visit(ElementB element);
          public void visit(ElementC element);
          }

          • VisitorA.java
          public class VisitorA implements IVisitor { 
          public void visit(ElementA element) {
          element.operationA();
          }

          public void visit(ElementB element) {
          element.operationB();
          }

          public void visit(ElementC element) {
          element.operationC();
          }
          }

          • Main.java
          public class Main { 
          public static void main(String[] args) {
          // know nothing about their type
          // after storing them into Element array
          IElement[] list = {new ElementA(),
          new ElementB(),
          new ElementC()};

          IVisitor visitor = new VisitorA();

          for (int i=0; i < list.length; i++)
          list[i].accept(visitor);
          }
          }

          Visitor訪問是基於overload來完成,對於每一個實現IElement的物件來說,它接受IVisitor來訪問它,在accept()方法中,IVisitor使用正確的方法來訪問IElement(顯然的,這麼部份可以靠不同的函式名稱,或是overload來達成),並在visit() 中對IElement作出對應的操作,如果您今天想要換掉每一個IElement的操作,只要更換IVisitor類型的物件就可以了,也就是這行:
           // IVisitor visitor = new VisitorA();
           // 換掉一個IVisitor,就可以換掉所有的操作
           // 不用修改多個地方
           IVisitor visitor = new VisitorB();
           

          舉個實際的例子,假設VisitorA只是個懶惰的推銷員好了,今天有一個比較勤快的推銷員VisitorB,在訪問過IElement之後,會對 IElement作出更多的操作,要在程式中實現VisitorB,只要增加一個VisitorB類別就可以了:
          • VisitorB.java
          public class VisitorB implements IVisitor { 
          public void visit(ElementA element) {
          System.out.println("VisitorB is a hard worker....");
          element.operationA();
          System.out.println(
          "I want to do some extra work on A....");
          }

          public void visit(ElementB element) {
          System.out.println("VisitorB is a hard worker....");
          element.operationB();
          System.out.println(
          "I want to do some extra work on B....");
          }

          public void visit(ElementC element) {
          System.out.println("VisitorB is a hard worker....");
          element.operationC();
          System.out.println(
          "I want to do some extra work on C....");
          }
          }

          改一下Main來示範:
          • Main.java
          public class Main { 
          public static void main(String[] args) {
          IElement[] list = {new ElementA(),
          new ElementB(),
          new ElementC()};

          System.out.println("visitorA is coming.......");
          IVisitor visitorA = new VisitorA();
          for (int i=0; i < list.length; i++)
          list[i].accept(visitorA);

          System.out.println("\nvisitorB is coming.......");
          IVisitor visitorB = new VisitorB();
          for (int i=0; i < list.length; i++)
          list[i].accept(visitorB);
          }
          }

          在範例中的System.out.println();只是個示意,它也可能是您對IElement的額外方法的直接調用。

          Visitor模式的 UML 結構類圖如下:
          Visitor

          Java World中有一篇文章,提到可以利用reflection來改進使用訪問者模式時的彈性,有興趣的可以進一步參考一下Reflect on the Visitor design pattern
          posted on 2007-04-17 10:53 張金鵬 閱讀(273) 評論(0)  編輯  收藏 所屬分類: Behavioral 模式
          主站蜘蛛池模板: 淮阳县| 泽州县| 碌曲县| 鸡泽县| 竹北市| 安西县| 宁阳县| 九龙城区| 上犹县| 潼关县| 拜泉县| 烟台市| 永泰县| 峡江县| 珲春市| 依安县| 怀安县| 三都| 玉门市| 长顺县| 于都县| 泊头市| 荔浦县| 翼城县| 乌恰县| 田阳县| 额尔古纳市| 武乡县| 密云县| 贵定县| 延寿县| 沙洋县| 房产| 洪泽县| 榕江县| 行唐县| 宝坻区| 公主岭市| 绵阳市| 彭山县| 壤塘县|