<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 16.7 訪問器模式 接下來,讓我們思考如何將具有完全不同目標的一個設計模式應用到垃圾歸類系統。 對這個模式,我們不再關心在系統中加入新型`Trash`時的優化。事實上,這個模式使新型`Trash`的添加顯得更加復雜。假定我們有一個基本類結構,它是固定不變的;它或許來自另一個開發者或公司,我們無權對那個結構進行任何修改。然而,我們又希望在那個結構里加入新的多態性方法。這意味著我們一般必須在基類的接口里添加某些東西。因此,我們目前面臨的困境是一方面需要向基類添加方法,另一方面又不能改動基類。怎樣解決這個問題呢? “訪問器”(`Visitor`)模式使我們能擴展基本類型的接口,方法是創建類型為`Visitor`的一個獨立的類結構,對以后需對基本類型采取的操作進行虛擬。基本類型的任務就是簡單地“接收”訪問器,然后調用訪問器的動態綁定方法。看起來就象下面這樣: ![](https://box.kancloud.cn/66baf8e8ffd4ee1db267ba488f76c20b_445x595.gif) 現在,假如v是一個指向`Aluminum`(鋁制品)的`Visitable`引用,那么下述代碼: ``` PriceVisitor pv = new PriceVisitor(); v.accept(pv); ``` 會造成兩個多態性方法調用:第一個會選擇`accept()`的`Aluminum`版本;第二個則在`accept()`里——用基類`Visitor`引用`v`動態調用`visit()`的特定版本時。 這種配置意味著可采取`Visitor`的新子類的形式將新的功能添加到系統里,沒必要接觸`Trash`結構。這就是“訪問器”模式最主要的優點:可為一個類結構添加新的多態性功能,同時不必改動結構——只要安裝好了`accept()`方法。注意這個優點在這兒是有用的,但并不一定是我們在任何情況下的首選方案。所以在最開始的時候,就要判斷這到底是不是自己需要的方案。 現在注意一件沒有做成的事情:訪問器方案防止了從主控`Trash`序列向單獨類型序列的歸類。所以我們可將所有東西都留在單主控序列中,只需用適當的訪問器通過那個序列傳遞,即可達到希望的目標。盡管這似乎并非訪問器模式的本意,但確實讓我們達到了很希望達到的一個目標(避免使用RTTI)。 訪問器模式中的雙生分發負責同時判斷`Trash`以及`Visitor`的類型。在下面的例子中,大家可看到`Visitor`的兩種實現方式:`PriceVisitor`用于判斷總計及價格,而`WeightVisitor`用于跟蹤重量。 可以看到,所有這些都是用回收程序一個新的、改進過的版本實現的。而且和`DoubleDispatch.java`一樣,`Trash`類被保持孤立,并創建一個新接口來添加`accept()`方法: ``` //: Visitable.java // An interface to add visitor functionality to // the Trash hierarchy without modifying the // base class. package c16.trashvisitor; import c16.trash.*; interface Visitable { // The new method: void accept(Visitor v); } ///:~ ``` `Aluminum`,`Paper`,`Glass`以及`Cardboard`的子類型實現了`accept()`方法: ``` //: VAluminum.java // Aluminum for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VAluminum extends Aluminum implements Visitable { public VAluminum(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~ //: VPaper.java // Paper for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VPaper extends Paper implements Visitable { public VPaper(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~ //: VGlass.java // Glass for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VGlass extends Glass implements Visitable { public VGlass(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~ //: VCardboard.java // Cardboard for the visitor pattern package c16.trashvisitor; import c16.trash.*; public class VCardboard extends Cardboard implements Visitable { public VCardboard(double wt) { super(wt); } public void accept(Visitor v) { v.visit(this); } } ///:~ ``` 由于`Visitor`基類沒有什么需要實在的東西,可將其創建成一個接口: ``` //: Visitor.java // The base interface for visitors package c16.trashvisitor; import c16.trash.*; interface Visitor { void visit(VAluminum a); void visit(VPaper p); void visit(VGlass g); void visit(VCardboard c); } ///:~ c16.TrashVisitor.VGlass:54 c16.TrashVisitor.VPaper:22 c16.TrashVisitor.VPaper:11 c16.TrashVisitor.VGlass:17 c16.TrashVisitor.VAluminum:89 c16.TrashVisitor.VPaper:88 c16.TrashVisitor.VAluminum:76 c16.TrashVisitor.VCardboard:96 c16.TrashVisitor.VAluminum:25 c16.TrashVisitor.VAluminum:34 c16.TrashVisitor.VGlass:11 c16.TrashVisitor.VGlass:68 c16.TrashVisitor.VGlass:43 c16.TrashVisitor.VAluminum:27 c16.TrashVisitor.VCardboard:44 c16.TrashVisitor.VAluminum:18 c16.TrashVisitor.VPaper:91 c16.TrashVisitor.VGlass:63 c16.TrashVisitor.VGlass:50 c16.TrashVisitor.VGlass:80 c16.TrashVisitor.VAluminum:81 c16.TrashVisitor.VCardboard:12 c16.TrashVisitor.VGlass:12 c16.TrashVisitor.VGlass:54 c16.TrashVisitor.VAluminum:36 c16.TrashVisitor.VAluminum:93 c16.TrashVisitor.VGlass:93 c16.TrashVisitor.VPaper:80 c16.TrashVisitor.VGlass:36 c16.TrashVisitor.VGlass:12 c16.TrashVisitor.VGlass:60 c16.TrashVisitor.VPaper:66 c16.TrashVisitor.VAluminum:36 c16.TrashVisitor.VCardboard:22 ``` 程序剩余的部分將創建特定的`Visitor`類型,并通過一個`Trash`對象列表發送它們: ``` //: TrashVisitor.java // The "visitor" pattern package c16.trashvisitor; import c16.trash.*; import java.util.*; // Specific group of algorithms packaged // in each implementation of Visitor: class PriceVisitor implements Visitor { private double alSum; // Aluminum private double pSum; // Paper private double gSum; // Glass private double cSum; // Cardboard public void visit(VAluminum al) { double v = al.weight() * al.value(); System.out.println( "value of Aluminum= " + v); alSum += v; } public void visit(VPaper p) { double v = p.weight() * p.value(); System.out.println( "value of Paper= " + v); pSum += v; } public void visit(VGlass g) { double v = g.weight() * g.value(); System.out.println( "value of Glass= " + v); gSum += v; } public void visit(VCardboard c) { double v = c.weight() * c.value(); System.out.println( "value of Cardboard = " + v); cSum += v; } void total() { System.out.println( "Total Aluminum: $" + alSum + "\n" + "Total Paper: $" + pSum + "\n" + "Total Glass: $" + gSum + "\n" + "Total Cardboard: $" + cSum); } } class WeightVisitor implements Visitor { private double alSum; // Aluminum private double pSum; // Paper private double gSum; // Glass private double cSum; // Cardboard public void visit(VAluminum al) { alSum += al.weight(); System.out.println("weight of Aluminum = " + al.weight()); } public void visit(VPaper p) { pSum += p.weight(); System.out.println("weight of Paper = " + p.weight()); } public void visit(VGlass g) { gSum += g.weight(); System.out.println("weight of Glass = " + g.weight()); } public void visit(VCardboard c) { cSum += c.weight(); System.out.println("weight of Cardboard = " + c.weight()); } void total() { System.out.println("Total weight Aluminum:" + alSum); System.out.println("Total weight Paper:" + pSum); System.out.println("Total weight Glass:" + gSum); System.out.println("Total weight Cardboard:" + cSum); } } public class TrashVisitor { public static void main(String[] args) { Vector bin = new Vector(); // ParseTrash still works, without changes: ParseTrash.fillBin("VTrash.dat", bin); // You could even iterate through // a list of visitors! PriceVisitor pv = new PriceVisitor(); WeightVisitor wv = new WeightVisitor(); Enumeration it = bin.elements(); while(it.hasMoreElements()) { Visitable v = (Visitable)it.nextElement(); v.accept(pv); v.accept(wv); } pv.total(); wv.total(); } } ///:~ ``` 注意`main()`的形狀已再次發生了變化。現在只有一個垃圾(`Trash`)筒。兩個`Visitor`對象被接收到序列中的每個元素內,它們會完成自己份內的工作。`Visitor`跟蹤它們自己的內部數據,計算出總重和價格。 最好,將東西從序列中取出的時候,除了不可避免地向`Trash`轉換以外,再沒有運行期的類型驗證。若在Java里實現了參數化類型,甚至那個轉換操作也可以避免。 對比之前介紹過的雙重分發方案,區分這兩種方案的一個辦法是:在雙重分發方案中,每個子類創建時只會重載其中的一個重載方法,即`add()`。而在這里,每個重載的`visit()`方法都必須在`Visitor`的每個子類中進行重載。 (1) 更多的結合? 這里還有其他許多代碼,`Trash`結構和`Visitor`結構之間存在著明顯的“結合”(`Coupling`)關系。然而,在它們所代表的類集內部,也存在著高度的凝聚力:都只做一件事情(`Trash`描述垃圾或廢品,而`Visitor`描述對垃圾采取什么行動)。作為一套優秀的設計模式,這無疑是個良好的開端。當然就目前的情況來說,只有在我們添加新的`Visitor`類型時才能體會到它的好處。但在添加新類型的`Trash`時,它卻顯得有些礙手礙腳。 類與類之間低度的結合與類內高度的凝聚無疑是一個重要的設計目標。但只要稍不留神,就可能妨礙我們得到一個本該更出色的設計。從表面看,有些類不可避免地相互間存在著一些“親密”關系。這種關系通常是成對發生的,可以叫作“對聯”(`Couplet`)——比如集合和迭代器(`Enumeration`)。前面的`Trash-Visitor`對似乎也是這樣的一種“對聯”。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看