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

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

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

    鷹翔宇空

    學習和生活

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      110 Posts :: 141 Stories :: 315 Comments :: 1 Trackbacks

    引自:http://www.tkk7.com/flyingis/archive/2005/11/09/18958.html


    2.Commons Collections中的算子
    算子成為Commons Collections 3.1中的有趣的部分有兩個原因:它們沒有得到應得的重視并且它們有改變你編程的方式的潛力。算子只是一個奇特的名字,它代表了一個包裝了函數的對象—一個“函數對象”。當然,它們不是一回事。如果你曾經使用過C和C++的方法指針,你就會理解算子的威力。
    一個算子是一個對象—一個Predicate,一個Closure, 一個Transformer。

    Predicates求對象的值并返回一個boolean,Transformer求對象的值并返回新對象,Closure接受對象并執行代碼。算子可以被組合成組合算子來模仿循環,邏輯表達式,和控制結構,并且算子也可以被用來過濾和操作集合中的元素。在這么短的篇幅中解釋清楚算子是不可能的,所以跳過介紹,我將會通過使用和不使用算子來解決同一問題(解釋算子)。在這個例子中,從一個ArrayList中而來的Student對象會被排序到兩個List中,如果他們符合某種標準的話。

    成績為A的學生會被加到honorRollStudents(光榮榜)中,得D和F的學生被加到problemStudents (問題學生)list中。學生分開以后,系統將會遍歷每個list,給加入到光榮榜中學生一個獎勵,并安排與問題學生的家長談話的時間表。下面的代碼不使用算子實現了這個過程:

    				List allStudents = getAllStudents();

    // 創建兩個ArrayList來存放榮譽學生和問題學生
    List honorRollStudents = new ArrayList();
    List problemStudents = new ArrayList();

    // 遍歷所有學生,將榮譽學生放入一個List,問題學生放入另一個
    Iterator allStudentsIter = allStudents.iterator();
    while( allStudentsIter.hasNext() ) {
    ??Student s = (Student) allStudentsIter.next();

    ??if( s.getGrade().equals( "A" ) ) {
    ????honorRollStudents.add( s );
    ??} else if( s.getGrade().equals( "B" ) &&
    ???????????? s.getAttendance() == PERFECT) {
    ????honorRollStudents.add( s );
    ??} else if( s.getGrade().equals( "D" ) ||
    ???????????? s.getGrade().equals( "F" ) ) {
    ????problemStudents.add( s );
    ??} else if( s.getStatus() == SUSPENDED ) {
    ????problemStudents.add( s );
    ??}
    }

    // 對于的有榮譽學生,增加一個獎勵并存儲到數據庫中
    Iterator honorRollIter =
    ????honorRollStudents.iterator();
    while( honorRollIter.hasNext() ) {
    ??Student s = (Student) honorRollIter.next();
    ??
    // 給學生記錄增加一個獎勵
    ??s.addAward( "honor roll", 2005 );
    ??Database.saveStudent( s );
    }

    // 對所有問題學生,增加一個注釋并存儲到數據庫中
    Iterator problemIter = problemStudents.iterator();
    while( problemIter.hasNext() ) {
    ??Student s = (Student) problemIter.next();

    ??// 將學生標記為需特殊注意
    ??s.addNote( "talk to student", 2005 );
    ??s.addNote( "meeting with parents", 2005 );
    ??Database.saveStudent( s );
    }



    上述例子是非常過程化的;要想知道Student對象發生了什么事必須遍歷每一行代碼。例子的第一部分是基于成績和考勤對Student對象進行邏輯判斷。

    第二部分對Student對象進行操作并存儲到數據庫中。像上述這個有著50行代碼程序也是大多程序所開始的—可管理的過程化的復雜性。但是當需求變化時,問題出現了。一旦判斷邏輯改變,你就需要在第一部分中增加更多的邏輯表達式。

    舉例來說,如果一個有著成績B和良好出勤記錄,但有五次以上的留堂記錄的學生被判定為問題學生,那么你的邏輯表達式將會如何處理?或者對于第二部分中,只有在上一年度不是問題學生的學生才能進入光榮榜的話,如何處理?當例外和需求開始改變進而影響到過程代碼時,可管理的復雜性就會變成不可維護的面條式的代碼。

    從上面的例子中回來,考慮一下那段代碼到底在做什么。它在一個List遍歷每一個對象,檢查標準,如果適用該標準,對此對象進行某些操作。上述例子可以進行改進的關鍵一處在于從代碼中將標準與動作解藕開來。下面的兩處代碼引用以一種非常不同的方法解決了上述的問題。首先,榮譽榜和問題學生的標準被兩個Predicate對象模型化了,并且加之于榮譽學生和問題學生上的動作也被兩個Closure對象模型化了。這四個對象如下定義:

    				import org.apache.commons.collections.Closure;
    import org.apache.commons.collections.Predicate;

    // 匿名的Predicate決定一個學生是否加入榮譽榜
    Predicate isHonorRoll = new Predicate() {
    ??public boolean evaluate(Object object) {
    ????Student s = (Student) object;

    ????return( ( s.getGrade().equals( "A" ) ) ||
    ????????????( s.getGrade().equals( "B" ) &&
    ??????????????s.getAttendance() == PERFECT ) );
    ??}
    };

    //匿名的Predicate決定一個學生是否是問題學生
    Predicate isProblem = new Predicate() {
    ??public boolean evaluate(Object object) {
    ????Student s = (Student) object;

    ????return ( ( s.getGrade().equals( "D" ) ||
    ?????????????? s.getGrade().equals( "F" ) ) ||
    ???????????? s.getStatus() == SUSPENDED );
    ??}
    };

    //匿名的Closure將一個學生加入榮譽榜
    Closure addToHonorRoll = new Closure() {
    ??public void execute(Object object) {
    ????Student s = (Student) object;
    ??????
    // 對學生增加一個榮譽記錄
    ????s.addAward( "honor roll", 2005 );
    ????Database.saveStudent( s );
    ??}
    };

    // 匿名的Closure將學生標記為需特殊注意
    Closure flagForAttention = new Closure() {
    ??public void execute(Object object) {
    ????Student s = (Student) object;
    ??????
    // 標記學生為需特殊注意
    ????s.addNote( "talk to student", 2005 );
    ????s.addNote( "meeting with parents", 2005 );
    ????Database.saveStudent( s );
    ??}
    };



    這四個匿名的Predicate和Closure是從作為一個整體互相分離的。flagForAttention(標記為注意)并不知道什么是確定一個問題學生的標準 ?,F在需要的是將正確的Predicate和正確的Closure結合起來的方法,這將在下面的例子中展示:

    				import org.apache.commons.collections.ClosureUtils;
    import org.apache.commons.collections.CollectionUtils;
    import org.apache.commons.collections.functors.NOPClosure;

    Map predicateMap = new HashMap();

    predicateMap.put( isHonorRoll, addToHonorRoll );
    predicateMap.put( isProblem, flagForAttention );
    predicateMap.put( null, ClosureUtils.nopClosure() );

    Closure processStudents =
    ????ClosureUtils.switchClosure( predicateMap );

    CollectionUtils.forAllDo( allStudents, processStudents );



    在上面的代碼中,predicateMap將Predicate與Closure進行了配對;如果一個學生滿足作為鍵值的Predicate的條件,那么它將把它的值傳到作為Map的值的Closure中。通過提供一個NOPClosure值和null鍵對,我們將把不符合任何Predicate條件的Student對象傳給由ClosureUtils調用創建的“不做任何事”或者“無操作”的NOPClosure。

    一個SwitchClosure, processStudents,從predicateMap中創建。并且通過使用CollectionUtils.forAllDo()方法,將processStudents Closure應用到allStudents中的每一個Student對象上。這是非常不一樣的處理方法;記住,你并沒有遍歷任何隊列。而是通過設置規則和因果關系,以及CollectionUtils和SwitchClosur來完成了這些操作。

    當你將使用Predicate的標準與使用Closure的動作將分離開來時,你的代碼的過程式處理就少了,而且更容易測試了。isHonorRoll Predicate能夠與addToHonorRoll Closure分離開來進行獨立的單元測試,它們也可以合起來通過使用Student類的模仿對象進行測試。第二個例子也會演示CollectionUtils.forAllDo(),它將一個Closure應用到了一個Collection的每一個元素中。

    你也許注意到了使用算子并沒用減少代碼行數,實際上,使用算子還增加了代碼量。但是,通過算子,你得到了將到了標準與動作的模塊性與封裝性的好處。如果你的代碼題已經接近于幾百行,那么請考慮一下更少過程化處理,更多面向對象的解決方案—通過使用算子。

    Jakarta Commons Cookbook中的第四章“算子”介紹了Commons Collections中可用的算子,在第五章,“集合”中,向你展示了如何使用算子來操作Java 集合類API。

    所有的算子-- Closure, Predicate, 和 Transformer—能夠被合并為合并算子來處理任何種類的邏輯問題。switch, while和for結構能夠被SwitchClosure, WhileClosure, 和 ForClosure模型化。
    復合的邏輯表達式可以被多個Predicate構建,通過使用OrPredicate, AndPredicate, AllPredicate, 和 NonePredicate將它們相互聯接。Commons BeanUtils也包含了算子的實現被用來將算子應用到bean的屬性中-- BeanPredicate, BeanComparator, 和 BeanPropertyValueChangeClosure。算子是考慮底層的應用架構的不一樣的方法,它們可以很好地改造你編碼實現的方法。

    posted on 2006-01-13 12:37 TrampEagle 閱讀(231) 評論(0)  編輯  收藏 所屬分類: java
    主站蜘蛛池模板: 国产精品免费一级在线观看| 国产亚洲人成A在线V网站| 国产亚洲视频在线观看| 亚洲综合另类小说色区| 37pao成人国产永久免费视频 | 99久久综合国产精品免费| 婷婷国产偷v国产偷v亚洲| 亚洲国产另类久久久精品| 成人午夜性A级毛片免费| 四虎国产精品成人免费久久| 久久丫精品国产亚洲av| 精品无码国产污污污免费| 在线观看免费无码视频| 亚洲日韩看片无码电影| 亚洲狠狠婷婷综合久久久久| 国产在线国偷精品产拍免费| 在线免费观看h片| 亚洲AV无码片一区二区三区| 亚洲AV人无码综合在线观看| 在线免费视频一区| 免费精品99久久国产综合精品| 亚洲AV无码一区二区三区鸳鸯影院| 亚洲国产天堂在线观看| 亚洲成A∨人片天堂网无码| 最近免费中文在线视频| 国产日韩久久免费影院 | 嫩草成人永久免费观看| 国产精品亚洲一区二区三区久久 | 久久亚洲精品11p| 亚洲国产av美女网站| 亚洲综合在线另类色区奇米| 成年女性特黄午夜视频免费看| 污污网站免费观看| 成人免费一区二区三区 | 国产亚洲免费的视频看| 免费无码一区二区| 亚洲高清乱码午夜电影网| 亚洲毛片免费观看| 图图资源网亚洲综合网站| 久久久久亚洲精品天堂久久久久久 | 无码免费一区二区三区免费播放|