<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 16.8 RTTI真的有害嗎 本章的各種設計模式都在努力避免使用RTTI,這或許會給大家留下“RTTI有害”的印象(還記得可憐的`goto`嗎,由于給人印象不佳,根本就沒有放到Java里來)。但實際情況并非絕對如此。正確地說,應該是RTTI使用不當才“有害”。我們之所以想避免RTTI的使用,是由于它的錯誤運用會造成擴展性受到損害。而我們事前提出的目標就是能向系統自由加入新類型,同時保證對周圍的代碼造成盡可能小的影響。由于RTTI常被濫用(讓它查找系統中的每一種類型),會造成代碼的擴展能力大打折扣——添加一種新類型時,必須找出使用了RTTI的所有代碼。即使僅遺漏了其中的一個,也不能從編譯器那里得到任何幫助。 然而,RTTI本身并不會自動產生非擴展性的代碼。讓我們再來看一看前面提到的垃圾回收例子。這一次準備引入一種新工具,我把它叫作`TypeMap`。其中包含了一個`Hashtable`(散列表),其中容納了多個`Vector`,但接口非常簡單:可以添加(`add()`)一個新對象,可以獲得(`get()`)一個`Vector`,其中包含了屬于某種特定類型的所有對象。對于這個包含的散列表,它的關鍵在于對應的`Vector`里的類型。這種設計模式的優點(根據Larry O'Brien的建議)是在遇到一種新類型的時候,`TypeMap`會動態加入一種新類型。所以不管什么時候,只要將一種新類型加入系統(即使在運行期間添加),它也會正確無誤地得以接受。 我們的例子同樣建立在`c16.Trash`這個“包”(`Package`)內的`Trash`類型結構的基礎上(而且那兒使用的`Trash.dat`文件可以照搬到這里來)。 ``` //: DynaTrash.java // Using a Hashtable of Vectors and RTTI // to automatically sort trash into // vectors. This solution, despite the // use of RTTI, is extensible. package c16.dynatrash; import c16.trash.*; import java.util.*; // Generic TypeMap works in any situation: class TypeMap { private Hashtable t = new Hashtable(); public void add(Object o) { Class type = o.getClass(); if(t.containsKey(type)) ((Vector)t.get(type)).addElement(o); else { Vector v = new Vector(); v.addElement(o); t.put(type,v); } } public Vector get(Class type) { return (Vector)t.get(type); } public Enumeration keys() { return t.keys(); } // Returns handle to adapter class to allow // callbacks from ParseTrash.fillBin(): public Fillable filler() { // Anonymous inner class: return new Fillable() { public void addTrash(Trash t) { add(t); } }; } } public class DynaTrash { public static void main(String[] args) { TypeMap bin = new TypeMap(); ParseTrash.fillBin("Trash.dat",bin.filler()); Enumeration keys = bin.keys(); while(keys.hasMoreElements()) Trash.sumValue( bin.get((Class)keys.nextElement())); } } ///:~ ``` 盡管功能很強,但對`TypeMap`的定義是非常簡單的。它只是包含了一個散列表,同時`add()`負擔了大部分的工作。添加一個新類型時,那種類型的`Class`對象的引用會被提取出來。隨后,利用這個引用判斷容納了那類對象的一個`Vector`是否已存在于散列表中。如答案是肯定的,就提取出那個`Vector`,并將對象加入其中;反之,就將`Class`對象及新`Vector`作為一個“鍵-值”對加入。 利用`keys()`,可以得到對所有`Class`對象的一個“枚舉”(`Enumeration`),而且可用`get()`,可通過`Class`對象獲取對應的`Vector`。 `filler()`方法非常有趣,因為它利用了`ParseTrash.fillBin()`的設計——不僅能嘗試填充一個`Vector`,也能用它的`addTrash()`方法試著填充實現了`Fillable`(可填充)接口的任何東西。`filter()`需要做的全部事情就是將一個引用返回給實現了`Fillable`的一個接口,然后將這個引用作為參數傳遞給`fillBin()`,就象下面這樣: ``` ParseTrash.fillBin("Trash.dat", bin.filler()); ``` 為產生這個引用,我們采用了一個“匿名內部類”(已在第7章講述)。由于根本不需要用一個已命名的類來實現`Fillable`,只需要屬于那個類的一個對象的引用即可,所以這里使用匿名內部類是非常恰當的。 對這個設計,要注意的一個地方是盡管沒有設計成對歸類加以控制,但在`fillBin()`每次進行歸類的時候,都會將一個`Trash`對象插入`bin`。 通過前面那些例子的學習,`DynaTrash`類的大多數部分都應當非常熟悉了。這一次,我們不再將新的`Trash`對象置入類型`Vector`的一個`bin`內。由于`bin`的類型為`TypeMap`,所以將垃圾(`Trash`)丟進垃圾筒(`Bin`)的時候,`TypeMap`的內部歸類機制會立即進行適當的分類。在`TypeMap`里遍歷并對每個獨立的`Vector`進行操作,這是一件相當簡單的事情: ``` Enumeration keys = bin.keys(); while(keys.hasMoreElements()) Trash.sumValue( bin.get((Class)keys.nextElement())); ``` 就象大家看到的那樣,新類型向系統的加入根本不會影響到這些代碼,亦不會影響`TypeMap`中的代碼。這顯然是解決問題最圓滿的方案。盡管它確實嚴重依賴RTTI,但請注意散列表中的每個鍵-值對都只查找一種類型。除此以外,在我們增加一種新類型的時候,不會陷入“忘記”向系統加入正確代碼的尷尬境地,因為根本就沒有什么代碼需要添加。
                  <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>

                              哎呀哎呀视频在线观看