<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    PC的blog

    Finding... Thinking... Solving...

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      9 Posts :: 0 Stories :: 54 Comments :: 0 Trackbacks
    本文緊接使用重構(gòu)移除丑陋的if else代碼(4)

    上篇文章談到如何能夠徹底把這個switch也移除掉呢?很簡單,我們只需要在getSystemStatePerformer()方法被調(diào)用之前先創(chuàng)建所有 performer匿名類的實例,然后在該方法被調(diào)用時直接返回對應(yīng)的實力。 如何具體實現(xiàn)呢? 用Map, 請看代碼:

    package de.jingge.refactoring;

     

    import static de.jingge.refactoring.SystemState.*;

    import java.awt.Image;

    import java.awt.image.BufferedImage;

    import java.lang.reflect.Method;

    import java.util.Collections;

    import java.util.HashMap;

    import java.util.Map;

     

    /**

     *

     * 
    @author gejing@gmail.com

     
    */

    public class SystemStatePerformerFactory {

     

    private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();

       

        
    private Map<SystemState, SystemStatePerformer> performers;

     

        
    private SystemStatePerformerFactory() {

    }

     

        
    public static SystemStatePerformerFactory getInstance() {

            
    return INSTANCE;

        }

       

        
    private synchronized Map<SystemState, SystemStatePerformer> getPerformers()

                
    throws Exception {

            
    if (performers == null) {

                performers 
    = new HashMap<SystemState, SystemStatePerformer>();

                
    // call all @FactoryMethod using reflection

                
    for (Method m : getClass().getDeclaredMethods()) {

                    
    if (m.getAnnotation(FactoryMethod.class!= null) {

                        SystemStatePerformer p 
    = (SystemStatePerformer) m.invoke(

                                
    thisnew Object[]{});

                        performers.put(p.getState(), p);

                    }

                }

                
    // make it readonly

                performers 
    = Collections.unmodifiableMap(performers);

            }

            
    return performers;

        }

     

        
    public SystemStatePerformer getSystemStatePerformer(SystemState state) throws Exception{

            
    return getPerformers().get(state);

        }

     

    @FactoryMethod

        
    private SystemStatePerformer createLoggedInPerformer() {

            
    return new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif")) {

     

                @Override

                
    public void perform() {

                    
    // do something after logging in is successful,

                    
    // for example: show welcome dialog, open the last edit document, etc.

                }

            };

        }

     

    @FactoryMethod

        
    private SystemStatePerformer createLoggedOutPerformer() {

            
    return new SystemStatePerformer(LOGGEDOUT, getImage("loggedout.gif")) {

     

                @Override

                
    public void perform() {

                    
    // do something after logging out is successful,

                    
    // for example: free used resource, dispose GUI components, etc.            }

                }

            };

        }

     

    @FactoryMethod

        
    private SystemStatePerformer createIdlePerformer() {

            
    return new SystemStatePerformer(IDLE, getImage("idle.gif")) {

     

                @Override

                
    public void perform() {

                    
    // do something after the user is idle,

                    
    // for example: save the application state temporarily, lock the application, etc.

                }

            };

        }

     

        
    private Image getImage(String string) {

            
    return new BufferedImage(1010, BufferedImage.TYPE_4BYTE_ABGR);

        }

    }

    從代碼中可以看出,當(dāng)getPerformers()方法被第一次調(diào)用時,我們會為每一個performer匿名類創(chuàng)建一個實例,并且將它們納入Map的管 理之中,以后每次調(diào)用的時候,直接從Map里面提取對應(yīng)某個狀態(tài)的performer就可以了, switch可以舍棄了。 @FactoryMethod這個注釋是我自己寫的,使用它主要是為了避免每次新增加一個create***Performer()方法后,都必須修改 getSystemStatePerformer()。

    @FactoryMethod的代碼如下:

    package de.jingge.refactoring;

     

    import java.lang.annotation.ElementType;

    import java.lang.annotation.Retention;

    import java.lang.annotation.RetentionPolicy;

    import java.lang.annotation.Target;

     


    @Retention(RetentionPolicy.RUNTIME)

    @Target({ElementType.METHOD})

    public @interface FactoryMethod {


    }

    到這里整個重構(gòu)已經(jīng)結(jié)束了, 我們已經(jīng)將if else, switch完全從代碼里剔除了。

    讀過Refactoring to Patterns這本書的朋友可能會覺得,這里所作的一些和書中第七章最后一節(jié)Replace Conditional Dispatcher with Command完全一樣。 Well,第一眼看上去確實很像,但是看完我寫的所有代碼后,再仔細(xì)想一想,兩者還是有區(qū)別的(Refactoring to Patterns這本書寫的非常好,對此書,我可以說是愛不釋手,還曾經(jīng)寫過一篇書評。事實上,我這篇文章正式基于這本書的):

    1. Factory + annonymous類而不是每一個狀態(tài)一個具體的實體類。

        這樣處理問題, 類的數(shù)量大大減少,類關(guān)聯(lián)的復(fù)雜程度也大大減少,維護(hù)起來很方便。

    2. performer并不單單是一個command,它擁有狀態(tài),并且可以處理更多的邏輯。


    全文完。




    聲明:本文版權(quán)歸作者所有,如需轉(zhuǎn)載請注明出處。

    posted on 2008-08-04 03:48 polygoncell 閱讀(4622) 評論(37)  編輯  收藏

    Feedback

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 09:12 HiMagic!
    ifelse -> switch -> map
    其實代碼無所謂丑陋與否,只不過是心理作祟。關(guān)鍵在于怎樣最符合業(yè)務(wù)邏輯,怎樣最適應(yīng)業(yè)務(wù)場景。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 09:37 kkktop
    我們寫程序的本質(zhì)是解決問題,如果就是為了OO而OO,反而陷入了OO的泥潭,如果一個簡單的邏輯只是因為用多了ifelse,就覺得不好,不夠OO,我想就有點鉆牛角尖的味道,而不是code的badsmell了.
    本人的感覺(粗略看過)如果只看這個問題,是把簡單問題復(fù)雜化了.呵呵  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 09:42 kkktop
    這就像打蚊子,不能只選用大炮的,只要是合適的武器能解決問題就好.
      回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 09:42 LINQ
    平時寫這些只會讓效率更加的低下,業(yè)務(wù)邏輯封裝的時候倒是可以考慮這樣的方法,寫一個統(tǒng)一調(diào)用的接口!就像樓上說的不能為了OO而OO,OO的目的是為了提高效率和減少維護(hù)的成本!博主寫不的不錯,贊一個!  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 09:53 路過
    呵呵,一個業(yè)務(wù)實現(xiàn)的方法是多種多樣的,但,當(dāng)一個業(yè)務(wù)有簡單變的復(fù)雜時,回頭來看以前寫的方法就知道優(yōu)劣了,平時多鍛煉oo也無可厚非,集沙成塔。支持一下。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5)[未登錄] 2008-08-04 09:55 Brian
    一篇文章就能寫清楚的事情,不需要寫5篇吧?簡單事情復(fù)雜化!  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 11:44 霉干菜
    這么寫了如果以后代碼交給別人維護(hù)
    要交待得太多了把  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 13:25 leekiang
    別連放5篇到首頁,以免形成視覺污染。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 13:52 zhuxing
    如果簡單針對樓主的代碼,個人覺得這么重構(gòu)有點過了。

    我提出置疑,針對的是:你用工廠方法模式的理由充分嗎?

    我想強調(diào)兩點:
    1、再仔細(xì)揣摩一下你的需求。是不是用個靜態(tài)方法(creation method)的方式更合理一些?
    2、看一下你周圍的工作伙伴,這么寫會不會增大代碼的負(fù)責(zé)度?(這個問題的標(biāo)準(zhǔn)是有你的同伴來決定,不能自己判斷)


    最后強調(diào)一下:
    在學(xué)習(xí)模式導(dǎo)向重構(gòu)的時候,看看最基本的重構(gòu)技巧是否已經(jīng)熟悉了。我看你那個getPerformers()方法,就有點難受。為什么要把if語句嵌套的那么深呢???

      回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 14:41 polygoncell
    呵呵,大家的反應(yīng)很激烈啊!

    我這里只是使用一個簡單的例子來解釋如何使用重構(gòu)來移除if else,實際應(yīng)用邏輯當(dāng)然要復(fù)雜很多。

    的確有一些程序員覺得一個方法里面使用一大堆if else很方便,其實這只是對他自己方便,別人閱讀他的這一大堆if else會很頭疼。

    我這樣重構(gòu)看似增加了代碼量,實則封裝了大量的技術(shù)細(xì)節(jié)。

    建議大家去讀讀refactoring to patterns這本書,書中就講到了一個結(jié)對重構(gòu)(該書的作者和一個程序員)的例子,最開始那個程序員也覺得重構(gòu)完后,代碼量明顯增加,他很不爽,但是后來他熟悉了那些模式后才發(fā)現(xiàn)他以前的做法是錯誤的,應(yīng)該進(jìn)行這樣的重構(gòu)。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 14:49 ANTI CPC
    我支持樓主,他只是用一個簡單的例子來說明如何進(jìn)行重構(gòu)。對于實際的case,往往復(fù)雜的多,一個好的架構(gòu)開始的時候貌似增加了代碼,實際上后面維護(hù)起來就舒服很多了,切身體會。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 15:04 badqiu
    避免過度設(shè)計  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 17:29 Unmi
    @Brian
    寫成五篇,可以投放的廣告就能多多了。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 18:04 千里冰封
    @Unmi
    確實,我開始還以為是系統(tǒng)的廣告呢,原來是作者自己加的,有點那個了,我想做俯臥撐了  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 18:33 polygoncell
    @千里冰封

    呵呵,可別超過3個。 對了,你的那個音樂播放器挺不錯的。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 18:34 polygoncell
    @Unmi

    我也就是這次試驗一下這么寫,效果不好的話會考慮下次換個方式。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 18:46 polygoncell
    @zhuxing

    理論上來說,creation method也是可以的,不過這樣一來就導(dǎo)致Performer類和過多的其他類產(chǎn)生耦合(因為處理每一個狀態(tài)需要用到完全不同的類),我用factory就是為了保持performer干凈。要是一定要用creation method的話,performer都可以省了,直接寫一個復(fù)雜的enum,而每一個enum實例正好就是creation method。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 21:13 kkktop
    對于這個簡單的問題,覺得ifelse加上應(yīng)有的注釋,好過這么大堆復(fù)雜的實現(xiàn),加上注釋的好處也是便于維護(hù)和后人的理解,并不比這樣實現(xiàn)下來差很多  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 22:07 BeanSoft
    難道 Map 內(nèi)部實現(xiàn)不是 if-esle 嘛?

    計算原理三要素: 順序、循環(huán)與分支

    OO 只不過是重新封裝了一把.  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 22:22 polygoncell
    @BeanSoft

    map沒有使用一大團(tuán)if else,HashMap的代碼如下:

    public V get(Object key) {
    if (key == null)
    return getForNullKey();
    int hash = hash(key.hashCode());
    for (Entry<K,V> e = table[indexFor(hash, table.length)];
    e != null;
    e = e.next) {
    Object k;
    if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
    return e.value;
    }
    return null;
    }

    而且Map已經(jīng)封裝好了,對于我們使用者來說是沒有if else的。 現(xiàn)在編碼強調(diào)的是粒度適度,便于測試,便于閱讀。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-05 00:24 隔葉黃鶯
    @polygoncell
    一、二、三、四、五連著五篇這么投放廣告還能是試驗呀,俯臥撐超過三個就會死人的,你這樣 5*4=20,哎呀,要快差不多7個人了。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-05 02:21 polygoncell
    @隔葉黃鶯

    這位兄弟挺逗的!呵呵。那個4是怎么得來的?

    兄弟沒必要這么針對我吧,我沒招惹你吧。真的是做個實驗,你可以看看我以前的文章。

    哦,對了,樓上眾位兄弟哪位能夠幫我分析一下:我應(yīng)該有如何處理自己原創(chuàng)的文章的自由吧? 而且看與不看全憑自愿,為什么有些朋友的反應(yīng)會這么激烈?最好那些反應(yīng)過激的朋友能站出來說說你們的想法,大家交換一下意見,謝謝。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-05 09:43 zhuxing
    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-04 18:46 polygoncell
    @zhuxing

    理論上來說,creation method也是可以的,不過這樣一來就導(dǎo)致Performer類和過多的其他類產(chǎn)生耦合(因為處理每一個狀態(tài)需要用到完全不同的類),我用factory就是為了保持performer干凈。要是一定要用creation method的話,performer都可以省了,直接寫一個復(fù)雜的enum,而每一個enum實例正好就是creation method。


    大哥:只能說,俺長見識了! ~_~  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-05 17:03 polygoncell
    @zhuxing

    我又仔細(xì)的考慮了一下,覺得靜態(tài)方法在這里并不適用,因為我們需要針對不同的狀態(tài)寫出完全不同的邏輯來處理狀態(tài)。靜態(tài)方法通常適用于參數(shù)實例繁多而邏輯相同的情況。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-05 22:49 onlykeke
    其實我覺得 if else 很漂亮。不過我也不否認(rèn)模式應(yīng)用的好處。只是不要過度設(shè)計。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-06 18:04 zhuxing
    @polygoncell
    我也只是和你打個比喻

    繼承封裝變化....靜態(tài)能繼承嗎?
    ---------簡單工廠(靜態(tài)工廠方法)和工廠方法的最本質(zhì)區(qū)別

    如果你真的有封裝變化的需求,那你用工廠方法問題不大。如果現(xiàn)有變化比較少,而且能夠預(yù)想到的擴(kuò)展需求不大,就別用工廠方法了...


    當(dāng)然你可能有你特定的需求,而且也沒法三言兩句說的很清楚。說實在的,你的那個反射...什么什么的... 有點亂~_~


    你的代碼是在使用工廠方法,但是這個創(chuàng)建過程有點煩瑣...不需要搞成這樣  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-07 19:59 polygoncell
    @zhuxing

    那個反射主要是為了分析@FactoryMethod注釋,用意很清晰:減少不必要的編碼。狀態(tài)增加后,程序員只需要增加一個帶@FactoryMethod的方法就行了。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-08 09:31 zhuxing
    @polygoncell
    不知道你寫了幾年代碼了
      回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-08 15:33 polygoncell
    @zhuxing

    有些年頭了,不過寫java代碼還沒超過10年,你呢?

    你覺得這樣做繁瑣,請問如何做才簡單?能不能貼出你認(rèn)為簡單的代碼?有時候旁觀和自己動手做的感覺是完全不一樣的。還有,別忘了要把簡單留給使用你代碼的人,而把繁瑣留給自己。

    有msn么?咱倆好好聊聊。:-)  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-08-13 23:33 小高
    這個代碼比if 更丑陋 ..... 看了本書 就強用書上的東西 .... 很有問題 .......
    博主有團(tuán)隊工作的經(jīng)歷嗎 ...每個人都這樣寫(小提大作)...... 項目就真亂了....
    自己研究還差不多 ... 我打賭 你要是真的 遇到了 你還是用 if   回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-09-01 12:36 mikelij
    這樣重構(gòu)法不具普遍意義. 因為它只適合于enumeration. 如果是復(fù)雜條件呢. 我個人認(rèn)為這是design pattern的錯誤應(yīng)用.兄弟你中毒了.  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-09-25 11:08 iridiumcao
    5篇有點多,合為一篇看起來比較好。
    博主能整理下,把文檔和代碼打個包,提供下載,更好。~我很懶。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2008-09-25 14:42 iridiumcao
    HiMagic!
    ifelse -> switch -> map

    演了一遍,就是HiMagic總結(jié)的過程。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2009-08-25 12:30 zhuxinyu
    我也同樣認(rèn)為if .... else .. 過多應(yīng)該進(jìn)行重構(gòu)。 我這里沒有那么復(fù)雜,僅僅是將
    判斷的集中狀態(tài)也寫出枚舉。 語法通過switch....case.... 去判斷。 如果再復(fù)雜的話我會寫出lz第5片的模式。

    第三篇中,我有個疑問public abstract class SystemStatePerformer
    這里的SystemStatePerformer是抽象類,lz怎么將其實例化了呢
    new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif"))。 是否應(yīng)該單獨寫個類繼承此類?  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2009-11-20 23:28 rockallite
    @mikelij
    “這樣重構(gòu)法不具普遍意義. 因為它只適合于enumeration. 如果是復(fù)雜條件呢. 我個人認(rèn)為這是design pattern的錯誤應(yīng)用.兄弟你中毒了. ”

    同意 mikelij。

    polygoncell 的代碼重構(gòu),核心就是從 if-else 改到 switch 再改到 Map,其必要條件是:業(yè)務(wù)判斷條件只包含簡單的枚舉。假設(shè)發(fā)生變化的恰恰是判斷條件呢?polygoncell 的重構(gòu)把這種判斷條件可變的靈活性舍棄了,所以遇到以上假設(shè)的情況時,代碼就無可避免的需要作大量更改。而用原來的 if-else,代碼就很靈活,更改的地方也很少。  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2010-06-30 17:46 virus
    @霉干菜
    不這么做的代碼,如果要交給別人,需要講更多都不會明白  回復(fù)  更多評論
      

    # re: 使用重構(gòu)移除丑陋的if else代碼(5) 2012-01-05 11:06 sagt
    其實if else的丑陋說白了是不利于變化,難以修改。比如說你的if else里原來有50種情況,現(xiàn)在要增加兩種,則你恐怕要去所有if else里面小心的去看,很容易弄出bug來。而用繼承和多態(tài)的方法只需要在一個地方增加就可以了。  回復(fù)  更多評論
      


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 你懂的免费在线观看| 啦啦啦www免费视频| 亚洲人成影院午夜网站| 成人免费无码精品国产电影| 羞羞视频在线观看免费| 亚洲福利在线视频| 午夜神器成在线人成在线人免费 | 亚洲va在线va天堂va888www| 国产人在线成免费视频| 色多多A级毛片免费看| 亚洲午夜精品一区二区| 国产午夜免费福利红片| 久久免费观看国产精品| 亚洲Av无码国产一区二区 | 亚洲国产精品无码久久久秋霞1| 亚洲日韩VA无码中文字幕| 在线观看www日本免费网站| 欧亚一级毛片免费看| 亚洲精品视频在线观看免费| 亚洲Av无码乱码在线播放| 久久成人国产精品免费软件| 黄 色一级 成 人网站免费| 国产精品亚洲精品观看不卡| 久久久久噜噜噜亚洲熟女综合| 黄页网站免费在线观看| 国产无遮挡裸体免费视频在线观看 | 皇色在线免费视频| 亚洲国产精品嫩草影院| 无码乱人伦一区二区亚洲| 可以免费观看一级毛片黄a| 亚洲视频在线免费看| 最近更新免费中文字幕大全| 在线亚洲v日韩v| 亚洲中文字幕无码久久2020| 亚洲欧洲日产国产综合网| 亚洲国产精品第一区二区三区| 中国在线观看免费高清完整版| 暖暖免费日本在线中文| 一个人免费观看视频在线中文 | 中国极品美軳免费观看| 视频一区在线免费观看|