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

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                33.3 包裝模式群PK 我們講了這么多的設計模式,大家有沒有發覺在很多的模式中有些角色是不干活的?它們只是充當黔首作用,你有問題,找我,但我不處理,我讓其他人處理。最典型的就是代理模式了,代理角色接收請求然后傳遞到被代理角色處理。門面模式也是一樣,門面角色的任務就是把請求轉發到子系統。類似這種結構的模式還有很多,我們先給這種類型的模式定義一個名字,叫做包裝模式(wrapping pattern)。注意,包裝模式是一組模式而不是一個。包裝模式包括哪些設計模式呢?包裝模式包括:裝飾模式、適配器模式、門面模式、代理模式、橋梁模式。下面我們通過一組例子來說明這五個包裝模式的區別。 33.3.1 代理模式 現在很多明星都有經紀人,一般有什么事他們都會說:“你找我的經紀人談好了”,下面我們就看看這一過程怎么模擬。假設有一個追星族想找明星簽字,我們看看采用代理模式怎么實現。代理模式是包裝模式中的最一般的實現,類圖如圖33-6所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036f3f06b.jpg) 圖33-6 追星族找明星簽字 類圖很簡單,就是一個簡單的代理模式,我們來看明星的定義,明星接口如代碼清單33-29所示。 代碼清單33-29 明星接口 public?interface?IStar?{ ?????//明星都會簽名 ?????public?void?sign(); } 明星只有一個行為:簽字。我們來看明星的實現,如代碼清單33-30所示。 代碼清單33-30 明星 public?class?Singer?implements?IStar?{ ?????public?void?sign()?{ ?????????????System.out.println("明星簽字:我是XXX大明星"); ?????} } 經紀人與明星應該有相同的行為,比如說簽名,雖然經紀人不簽名,但是他把你要簽名的筆記本、衣服、CD等傳遞過去讓真正的明星簽字,經紀人如代碼清單33-31所示。 代碼清單33-31 經紀人 public?class?Agent?implements?IStar?{ ?????//定義是誰的經紀人 ?????private?IStar?star; ?????//構造函數傳遞明星 ?????public?Agent(IStar?_star){ ?????????????this.star?=?_star; ?????} ?????//經紀人是不會簽字的,簽字了歌迷也不認 ?????public?void?sign()?{ ?????????????star.sign(); ?????} } 應該非常明確地指出一個經紀人是誰的代理,因此要在構造函數中接收一個明星對象,確定是要做這個明星的代理。我們再來看看追星族是怎么找明星簽字的,如代碼清單33-32所示。 代碼清單33-32 追星族 public?class?Idolater?{ ?????public?static?void?main(String[]?args)?{ ?????????????//崇拜的明星是誰 ?????????????IStar?star?=?new?Singer(); ?????????????//找到明星的經紀人 ?????????????IStar?agent?=?new?Agent(star); ?????????????System.out.println("追星族:我是你的崇拜者,請簽名!"); ?????????????//簽字 ?????????????agent.sign(); ?????} } 很簡單,找到明星的代理,然后明星就簽字了。運行結果如下所示: 追星族:我是你的崇拜者,請簽名! 明星簽字:我是XXX大明星 看看我們的程序邏輯,我們是找明星的經紀人簽字,真實簽字的是明星,經紀人只是把這個請求傳遞給明星處理而已,這是普通的代理模式的典型應用。 33.3.2 裝飾模式 明星也都是一步一步地奮斗出來的,誰都不是一步就成為大明星的。甚至一些演員通過粉飾自己給觀眾一個好的印象,現在我們就來看怎么粉飾一個演員,如圖33-7所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036f52f3e.jpg) 圖33-7 演技修飾 下面我們就來看看這些過程如何實現,先看明星接口,如代碼清單33-33所示。 代碼清單33-33 明星接口 public?interface?IStar?{ ?????//演戲 ?????public?void?act(); } 我們來看看我們的主角,如代碼清單33-34所示。 代碼清單33-34 假明星 public?class?FreakStar?implements?IStar?{ ?????public?void?act()?{ ?????????????System.out.println("演中:演技很拙劣"); ?????} } 我們看看這個明星是怎么粉飾的,先定義一個抽象裝飾類,如代碼清單33-35所示。 代碼清單33-35 抽象裝飾類 public?abstract?class?Decorator?implements?IStar?{ ?????//粉飾的是誰 ?????private?IStar?star; ?????public?Decorator(IStar?_star){ ?????????????this.star?=?_star; ?????} ?????public?void?act()?{ ?????????????this.star.act(); ?????} } 前后兩次修飾,開演前毫無忌憚地吹噓,如代碼清單33-36所示。 代碼清單33-36 吹大話 public?class?HotAir?extends?Decorator?{ ?????public?HotAir(IStar?_star){ ?????????????super(_star); ?????} ?????public?void?act(){ ?????????????System.out.println("演前:夸夸其談,沒有自己不能演的角色"); ?????????????super.act(); ?????} } 大家發現這個明星演技不好的時候,他拼命找借口,說是那天天氣不好、心情不好等,如代碼清單33-37所示。 代碼清單33-37 抵賴 public?class?Deny?extends?Decorator?{ ?????public?Deny(IStar?_star){ ?????????????super(_star); ?????} ?????public?void?act(){ ?????????????super.act(); ?????????????System.out.println("演后:百般抵賴,死不承認"); ?????} } 我們建立一個場景把這種情況展示一下,如代碼清單33-38所示。 代碼清單33-38 場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//定義出所謂的明星 ?????????????IStar?freakStar?=?new?FreakStar(); ?????????????//看看他是怎么粉飾自己的 ?????????????//演前吹噓自己無所不能 ?????????????freakStar?=?new?HotAir(freakStar); ?????????????//演完后,死不承認自己演的不好 ?????????????freakStar?=?new?Deny(freakStar); ?????????????System.out.println("====看看一些虛假明星的形象===="); ?????????????freakStar.act(); ?????} } 運行結果如下所示: ====看看一些虛假明星的形象==== 演前:夸夸其談,沒有自己不能演的角色 演中:演技很拙劣 演后:百般抵賴,死不承認 33.3.3 適配器模式 我們知道在演藝圈中還存在一種情況:替身,替身也是演員,只是普通的演員而已,在一段戲中,前十五分鐘是明星本人,后十五分鐘也是明星本人,就中間的五分鐘是替身,那這個場景該怎么描述呢?注意中間那五分鐘,這個時候一個普通演員被導演認為是明星演員,我們來看類圖,如圖33-8所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036f6adc7.jpg) 圖33-8 替身演員類圖 導演找了一個普通演員作為明星的替身,不過觀眾看到的還是明星的身份。我們來看代碼,首先看明星接口,如代碼清單33-39所示。 代碼清單33-39 明星接口 public?interface?IStar?{ ?????//明星都要演戲 ?????public?void?act(String?context); } 再來看一個具體的電影明星,他的主要職責就是演戲,如代碼清單33-40所示。 代碼清單33-40 電影明星 public?class?FilmStar?implements?IStar?{ ?????public?void?act(String?context)?{ ?????????????System.out.println("明星演戲:"?+?context); ?????} } 我們再來看普通演員,明星就那么多,但是普通演員非常多,我們看其接口,如代碼清單33-41所示。 代碼清單33-41 普通演員接口 public?interface?IActor?{ ?????//普通演員演戲 ?????public?void?playact(String?contet); } 普通演員也是演員,是要演戲的,我們來看一個普通演員的實現,如代碼清單33-42所示。 代碼清單33-42 普通演員 public?class?UnknownActor?implements?IActor?{ ?????//普通演員演戲 ?????public?void?playact(String?context)?{ ?????????????System.out.println("普通演員:"+context); ?????} } 我們來看替身該怎么編寫,如代碼清單33-43所示。 代碼清單33-43 替身演員 public?class?Standin?implements?IStar?{ ?????private?IActor?actor; ?????//替身是誰 ?????public?Standin(IActor?_actor){ ?????????????this.actor?=?_actor; ?????} ?????public?void?act(String?context)?{ ?????????????actor.playact(context); ?????} } 這是一個通用的替身,哪個普通演員能擔任哪個明星的替身是由導演決定的,導演想讓誰當就讓誰當,我們來看導演,如代碼清單33-44所示。 代碼清單33-44 導演類 public?class?direcotr?{ ?????public?static?void?main(String[]?args)?{ ?????????????System.out.println("=======演戲過程模擬=========="); ?????????????//定義一個大明星 ?????????????IStar?star?=?new?FilmStar(); ?????????????star.act("前十五分鐘,明星本人演戲");????? ?????????????//導演把一個普通演員當做明星演員來用 ?????????????IActor?actor?=?new?UnknownActor(); ?????????????IStar?standin=?new?Standin(actor); ?????????????standin.act("中間五分鐘,替身在演戲"); ?????????????star.act("后十五分鐘,明星本人演戲");????? ?????} } 運行結果如下所示: =======演戲過程模擬========== 明星演戲:前十五分鐘,明星本人演戲 普通演員:中間五分鐘,替身在演戲 明星演戲:后十五分鐘,明星本人演戲 這里使用了適配器模式,把一個普通的演員轉換為一個明星演員。 33.3.4 橋梁模式 我們繼續說明星圈的事情,現在明星類型太多了,比如電影明星、電視明星、歌星、體育明星、網絡明星等,每個類型的明星都有明確的職責,電影明星的主要工作就是演電影,電視明星的主要工作就是演電視劇或者主持電視節目。再看看現在的明星,單一發展的基本沒有,主持人出專輯、體育明星演電影、歌星拍戲等太平常了,我們就用程序來表現一下多元化情形,如圖33-9所示。 ![](https://box.kancloud.cn/2016-08-14_57b0036f7ffbb.jpg) 圖33-9 各類明星描述 圖33-9中定義了一個抽象明星AbsStar,然后產生出各個具體類型的明星,比如電影明星FilmStar、歌星Singer,當然還可以繼續擴展下去。這里還定義了一個抽象的行為AbsAction,描述明星所具有的活動,比如演電影、唱歌等,在這種設計下,明星可以擴展,明星的活動也可以擴展,非常靈活。我們先來看明星的活動,抽象活動如代碼清單33-45所示。 代碼清單33-45 抽象活動 public?abstract?class?AbsAction?{ ?????//每個活動都有描述 ?????public?abstract?void?desc(); } 很簡單,只有一個活動的描述,由子類來實現。我們來看演電影和唱歌兩個活動,分別如代碼清單33-46、33-47所示。 代碼清單33-46 演電影 public?class?ActFilm?extends?AbsAction?{ ?????public?void?desc()?{ ?????????????System.out.println("演出精彩絕倫的電影"); ?????} } 代碼清單33-47 唱歌 public?class?Sing?extends?AbsAction?{ ?????public?void?desc()?{ ?????????????System.out.println("唱出優美的歌曲"); ?????} } 各種精彩的活動都有了,我們再來看抽象明星,它是所有明星的代表,如代碼清單33-48所示。 代碼清單33-48 抽象明星 public?abstract?class?AbsStar?{ ?????//一個明星參加哪些活動 ?????protected?final?AbsAction?action; ?????//通過構造函數傳遞具體活動 ?????public?AbsStar(AbstAction?_action){ ?????????????this.action?=?_action; ?????} ?????//每個明星都有自己的主要工作 ?????public?void?doJob(){ ?????????????action.desc(); ?????} } 明星都有自己的主要活動(或者是主要工作),我們在抽象明星中只是定義明星有活動,具體有什么活動由各個子類實現。我們再來看電影明星,如代碼清單33-49所示。 代碼清單33-49 電影明星 public?class?FilmStar?extends?AbsStar?{ ?????//默認的電影明星的主要工作是拍電影 ?????public?FilmStar(){ ?????????????super(new?ActFilm()); ?????} ?????//也可以重新設置一個新職業 ?????public?FilmStar(AbsAction?_action){ ?????????????super(_action); ?????} ?????//細化電影明星的職責 ?????public?void?doJob(){ ?????????????System.out.println("\n======影星的工作====="); ?????????????super.doJob(); ?????} } 電影明星的本職工作就應該是演電影,因此就有了一個無參構造函數來定義電影明星的默認工作,如果明星要客串一下去唱歌也可以,有參構造解決了該問題。歌星的實現與此相同,如代碼清單33-50所示。 代碼清單33-50 歌星 public?class?Singer?extends?AbsStar?{ ?????//歌星的默認活動是唱歌 ?????public?Singer(){ ?????????????super(new?Sing()); ?????} ?????//也可以重新設置一個新職業 ?????public?Singer(AbsAction?_action){ ?????????????super(_action); ?????} ?????//細化歌星的職責 ?????public?void?doJob(){ ?????????????System.out.println("\n======歌星的工作====="); ?????????????super.doJob(); ?????} } 我們使用電影明星和歌星來作為代表,這兩類明星也是我們經常聽到或看到的,下面建立一個場景類來模擬一下明星的事跡,如代碼清單33-51所示。 代碼清單33-51 場景類 public?class?Client?{ ?????public?static?void?main(String[]?args)?{ ?????????????//聲明一個電影明星 ?????????????AbsStar?zhangSan?=?new?FilmStar(); ?????????????//聲明一個歌星 ?????????????AbsStar?liSi?=?new?Singer(); ?????????????//展示一下各個明星的主要工作 ?????????????zhangSan.doJob(); ?????????????liSi.doJob(); ?????????????//當然,也有部分明星不務正業,比如歌星演戲 ?????????????liSi?=?new?Singer(new?ActFilm()); ?????????????liSi.doJob(); ?????} } 運行結果如下所示: ======影星的工作===== 演出精彩絕倫的電影 ======歌星的工作===== 唱出優美的歌曲 ======歌星的工作===== 演出精彩絕倫的電影 好了,各類明星都有自己的本職工作,但是偶爾客串一個其他類型的活動也是允許的,如此設計后,明星就可以不用固定在自己的本職工作上,而是向其他方向發展,比如影視歌三棲明星。 門面模式我們在其他章節已經講解得比較多了,本小節就不再贅述。 33.3.5 最佳實踐 5個包裝模式是大家在系統設計中經常會用到的模式,它們具有相似的特征:都是通過委托的方式對一個對象或一系列對象(例如門面模式)施行包裝,有了包裝,設計的系統才更加靈活、穩定,并且極具擴展性。從實現的角度來看,它們都是代理的一種具體表現形式,我們來看看它們在使用場景上有什么區別。 代理模式主要用在不希望展示一個對象內部細節的場景中,比如一個遠程服務不需要把遠程連接的所有細節都暴露給外部模塊,通過增加一個代理類,可以很輕松地實現被代理類的功能封裝。此外,代理模式還可以用在一個對象的訪問需要限制的場景中,比如AOP。 裝飾模式是一種特殊的代理模式,它倡導的是在不改變接口的前提下為對象增強功能,或者動態添加額外職責。就擴展性而言,它比子類更加靈活,例如在一個已經運行的項目中,可以很輕松地通過增加裝飾類來擴展系統的功能。 適配器模式的主要意圖是接口轉換,把一個對象的接口轉換成系統希望的另外一個接口,這里的系統指的不僅僅是一個應用,也可能是某個環境,比如通過接口轉換可以屏蔽外界接口,以免外界接口深入系統內部,從而提高系統的穩定性和可靠性。 橋梁模式是在抽象層產生耦合,解決的是自行擴展的問題,它可以使兩個有耦合關系的對象互不影響地擴展,比如對于使用筆畫圖這樣的需求,可以采用橋梁模式設計成用什么筆(鉛筆、毛筆)畫什么圖(圓形、方形)的方案,至于以后需求的變更,如增加筆的類型,增加圖形等,對該設計來說是小菜一碟。 門面模式是一個粗粒度的封裝,它提供一個方便訪問子系統的接口,不具有任何的業務邏輯,僅僅是一個訪問復雜系統的快速通道,沒有它,子系統照樣運行,有了它,只是更方便訪問而已。
                  <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>

                              哎呀哎呀视频在线观看