<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 功能強大 支持多語言、二開方便! 廣告
                21.4 組合模式的擴展 21.4.1 真實的組合模式 什么是真實的組合模式?就是你在實際項目中使用的組合模式,而不是僅僅依照書本上學習到的模式,它是“實踐出真知”。在我們的例子中,經過精簡后,確實是類、接口減少了很多,而且程序也簡單很多,但是大家可能還是很迷茫,這個Client程序并沒有改變多少呀,非常正確,樹的組裝是跑不了的,你要知道在項目中使用關系型數據庫來存儲這些信息,你可以從數據庫中直接提取出哪些人要分配到樹枝,哪些人要分配到樹葉,樹枝與樹枝、樹葉的關系等,這些都是由相關的業務人員維護到數據庫中的,通常這里是把數據存放到一張單獨的表中,表結構如圖21-7所示。 ![](https://box.kancloud.cn/2016-08-14_57b00367a2799.jpg) 圖21-7 關系數據庫中存儲的樹形結構 這張數據表定義了一個樹形結構,我們要做的就是從數據庫中把它讀取出來,然后展現到前臺上,用for循環加上遞歸就可以完成這個讀取。用了數據庫后,數據和邏輯已經在表中定義好了,我們直接讀取放到樹上就可以了,這個還是比較容易做的,大家不妨自己考慮一下。 這才是組合模式的真實引用,它依靠了關系數據庫的非對象存儲性能,非常方便地保存了一個樹形結構。大家可以在項目中考慮采用,想想看現在還有哪個項目不使用關系型數據庫呢? 21.4.2 透明的組合模式 組合模式有兩種不同的實現:透明模式和安全模式,我們上面講的就是安全模式,那透明模式是什么樣子呢?透明模式的通用類圖,如圖21-8所示。 ![](https://box.kancloud.cn/2016-08-14_57b00367ba833.jpg) 圖21-8 透明模式的通用類圖 我們與圖21-6所示的安全模式類圖對比一下就非常清楚了,透明模式是把用來組合使用的方法放到抽象類中,比如add()、remove()以及getChildren等方法(順便說一下,getChildren一般返回的結果為Iterable的實現類,很多,大家可以看JDK的幫助),不管葉子對象還是樹枝對象都有相同的結構,通過判斷是getChildren的返回值確認是葉子節點還是樹枝節點,如果處理不當,這個會在運行期出現問題,不是很建議的方式;安全模式就不同了,它是把樹枝節點和樹葉節點徹底分開,樹枝節點單獨擁有用來組合的方法,這種方法比較安全,我們的例子使用了安全模式。 由于透明模式的使用者還是比較多,我們也把它的通用源代碼共享出來,首先看抽象構件,如代碼清單21-22所示。 代碼清單21-22 抽象構件 public?abstract?class?Component?{ ?????//個體和整體都具有的共享 ?????public?void?doSomething(){ ?????????????//編寫業務邏輯 ?????} ?????//增加一個葉子構件或樹枝構件 ?????public?abstract?void?add(Component?component); ?????//刪除一個葉子構件或樹枝構件 ?????public?abstract?void?remove(Component?component); ?????//獲得分支下的所有葉子構件和樹枝構件 ?????public?abstract?ArrayList<Component>?getChildren(); } 抽象構件定義了樹枝節點和樹葉節點都必須具有的方法和屬性,這樣樹枝節點的實現就不需要任何變化,如代碼清單21-19所示。 樹葉節點繼承了Component抽象類,不想讓它改變有點難,它必須實現三個抽象方法,怎么辦?好辦,給個空方法,如代碼清單21-23所示。 代碼清單21-23 樹葉節點 public?class?Leaf?extends?Component?{ ?????@Deprecated ?????public?void?add(Component?component)?throws?UnsupportedOperationException{ ?????????????//空實現,直接拋棄一個"不支持請求"異常 ?????????????throw?new?UnsupportedOperationException(); ?????} ?????@Deprecated ?????public?void?remove(Component?component)throws?UnsupportedOperationException{ ?????????????//空實現 ?????????????throw?new?UnsupportedOperationException(); ?????} ?????@Deprecated ?????public?ArrayList<Component>?getChildren()throws?UnsupportedOperationException{ ?????????????//空實現 ?????????????throw?new?UnsupportedOperationException();?????????? ?????} } 為什么要加個Deprecated注解呢?就是在編譯器期告訴調用者,你可以調我這個方法,但是可能出現錯誤哦,我已經告訴你“該方法已經失效”了,你還使用那在運行期也會拋出UnsupportedOperationException異常。 在透明模式下,遍歷整個樹形結構是比較容易的,不用進行強制類型轉換,如代碼清單21-24所示。 代碼清單21-24 樹結構遍歷 public?class?Client?{ ?????//通過遞歸遍歷樹 ?????public?static?void?display(Component?root){ ?????????????for(Component?c:root.getChildren()){ ??????????????????if(c?instanceof?Leaf){?//葉子節點 ??????????????????????????c.doSomething(); ??????????????????}else{?//樹枝節點 ??????????????????????????display(c); ??????????????????} ??????????} ?????} } 僅僅在遍歷時不再進行牽制的類型轉化了,其他的組裝則沒有任何變化。透明模式的好處就是它基本遵循了依賴倒轉原則,方便系統進行擴展。 21.4.3 組合模式的遍歷 我們在上面也還提到了一個問題,就是樹的遍歷問題,從上到下遍歷沒有問題,但是我要是從下往上遍歷呢?比如組織機構這棵樹,我從中抽取一個用戶,要找到它的上級有哪些,下級有哪些,怎么處理?想想,再想想!想出來了吧,我們對下答案,類圖如圖21-9所示。 ![](https://box.kancloud.cn/2016-08-14_57b00367ce4fc.jpg) 圖21-9 增加父查詢的類圖 看類圖中,在Corp類中增加了兩個方法,setParent是設置父節點是誰,getParent是查找父節點是誰,我們來看一下程序的改變,如代碼清單21-25所示。 代碼清單21-25 抽象構件 public?abstract?class?Corp?{ ?????//公司每個人都有名稱 ?????private?String?name?=?""; ?????//公司每個人都職位 ?????private?String?position?=?""; ?????//公司每個人都有薪水 ?????private?int?salary?=0; ?????//父節點是誰 ?????private?Corp?parent?=?null; ?????public?Corp(String?_name,String?_position,int?_salary){ ?????????????this.name?=?_name; ?????????????this.position?=?_position; ?????????????this.salary?=?_salary; ?????} ?????//獲得員工信息 ?????public?String?getInfo(){ ?????????????String?info?=?""; ?????????????info?=?"姓名:"?+?this.name; ?????????????info?=?info?+?"\t職位:"+?this.position; ?????????????info?=?info?+?"\t薪水:"?+?this.salary; ?????????????return?info; ?????} ?????//設置父節點 ?????protected?void?setParent(Corp?_parent){ ?????????????this.parent?=?_parent; ?????} ?????//得到父節點 ?????public?Corp?getParent(){ ?????????????return?this.parent; ?????} } 就增加了粗體部分,然后我們再來看看樹枝節點的改變,如代碼清單21-26所示。 代碼清單21-26 樹枝構件 public?class?Branch?extends?Corp?{ ?????//領導下邊有哪些下級領導和小兵 ?????ArrayList<Corp>?subordinateList?=?new?ArrayList<Corp>(); ?????//構造函數是必需的 ?????public?Branch(String?_name,String?_position,int?_salary){ ?????????????super(_name,_position,_salary); ?????} ?????//增加一個下屬,可能是小頭目,也可能是個小兵 ?????public?void?addSubordinate(Corp?corp)?{ ?????????????corp.setParent(this);?//設置父節點 ?????????????this.subordinateList.add(corp); ?????} ?????//我有哪些下屬 ?????public?ArrayList<Corp>?getSubordinate()?{ ?????????????return?this.subordinateList; ?????} } 增加了粗體部分。看懂程序了嗎?甭管是樹枝節點還是樹葉節點,在每個節點都增加了一個屬性:父節點對象,這樣在樹枝節點增加子節點或葉子節點是設置父節點,然后你看整棵樹除了根節點外每個節點都有一個父節點,剩下的事情還不好處理嗎?每個節點上都有父節點了,你要往上找,那就找唄!大家自己考慮一下,寫個find方法,然后一步一步往上找,非常簡單的方法,這里就不再贅述。 有了這個parent屬性,什么后序遍歷(從下往上找)、中序遍歷(從中間某個環節往上或往下遍歷)都解決了,這個就不多說了。 再提一個問題,樹葉節點和樹枝節點是有順序的,你不能亂排,怎么辦?比如我們上面的例子,研發一組下邊有3個成員,這3個成員要進行排序(在機關里這叫做排位,同樣是同事也有個先后升遷順序),你怎么處理?問我呀,問你呢,好好想想,以后用得著的!
                  <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>

                              哎呀哎呀视频在线观看