很久很久以前

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            34 隨筆 :: 4 文章 :: 17 評論 :: 0 Trackbacks

          http://dev2dev.bea.com.cn/bbs/thread.jspa?forumID=125&threadID=27195
          Design Pattern Practice
          1.序
          本文從一個簡單的多列排序的例子入手,由淺入深地講解Design Pattern(設計模式)的目的、分析和實踐。
          文中的例子用到Compositor Pattern和Decorator Pattern。
          同時,文中的例子也提供了一類問題(條件組合問題)的解決方案。

          2.問題的引入
          Design Pattern(設計模式)的目標是,把共通問題中的不變部分和變化部分分離出來。不變的部分,就構成了Design Pattern(設計模式)。這一點和Framework(框架)有些象。
          下面舉個排序的例子,說明如何抽取問題中的不變部分。
          假設一個Java類Record有field1,field2,field3等字段。
          java代碼:?


          public?class?Record{?
          ????????
          public?int?field1;?
          ????????
          public?long?field2;?
          ????????
          public?double?filed3;?
          }
          ;?





          我們還有一個Record對象的數組Record[] records。我們需要對這個數組按照不同的條件排序。
          首先,按照field1的大小從小到大進行升序排序。
          排序函數如下:
          java代碼:?


          void?sort(Record[]?records){?
          ????????
          for(int?i?=….){?
          ????????????????
          for(int?j=….){?
          ????????????????????????
          if(records.field1?>?records[j].field1)?
          ????????????????????????????????
          //?swap?records?and?records[j]?
          ????????????????}
          ?
          ????????}
          ?
          }
          ?





          其次,按照field2的大小從小到大進行升序排序。
          java代碼:?


          void?sort(Record[]?records){?
          ????????
          for(int?i?=….){?
          ????????????????
          for(int?j=….){?
          ????????????????????????
          if(records.field2?>?records[j].field2)?
          ????????????????????????????????
          //?swap?records?and?records[j]?
          ????????????????}
          ?
          ????????}
          ?
          }
          ?





          再次,按照field3的大小從小到大進行升序排序。
          這種要求太多了,我們寫了太多的重復代碼。我們可以看到,問題的變化部分,只有判斷條件部分(黑體的if條件判斷語句)。
          我們可以引入一個Comparator接口,把這個變化的部分抽取出來。
          java代碼:?


          public?interface?Comparator(){?
          ????????
          public?boolean?greaterThan(Record?a,?Record?b);?
          }
          ;?
          sort函數就可以這樣寫(把判斷條件作為參數):?
          void?sort(Record[]?records,?Comparator?compare){?
          ????????
          for(int?i?=….){?
          ????????????????
          for(int?j=….){?
          ????????????????????????
          if(compare.greaterThen(records,?records[j]))?
          ????????????????????????????????
          //?swap?records?and?records[j]?
          ????????????????}
          ?
          ????????}
          ?
          }
          ?





          這樣,對應第一個要求——對records數組按照field1的大小排序。
          我們可以做一個實現Comparator接口的CompareByField1類。
          java代碼:?


          public?class?CompareByField1?implements?Comparator{?
          public?boolean?greaterThan(Record?a,?Record?b){?
          ????????
          if(a.filed1?>?b.filed1){?
          ????????????????
          return?ture;?
          ????????}
          ?
          ????????
          return?false;?
          }
          ?
          }
          ?





          sort函數的調用為:sort(records, new CompareByField1());

          這樣,對應第一個要求——對records數組按照field2的大小排序。
          我們可以做一個實現Comparator接口的CompareByField2類。

          java代碼:?


          public?class?CompareByField2?implements?Comparator{?
          public?boolean?greaterThan(Record?a,?Record?b){?
          ????????
          if(a.filed2?>?b.filed2){?
          ????????????????
          return?ture;?
          ????????}
          ?
          ????????
          return?false;?
          }
          ?
          }
          ?




          sort函數的調用為:sort(records, new CompareByField2());
          按照C++ STL的叫法,這里的sort稱為算法(Algorithm),records稱為容器(集合),Comparator稱為函數對象(Function Object)。

          JDK的java.util.Collections類的sort方法和java.util.Comparator接口就是按照這樣的思路設計的。下面我們來看看如何應用sort和Comparator解決多列排序問題。

          3.多列排序問題
          3.1排序條件的數量
          我們知道,SQL語句能夠實現強大的排序功能,能夠按照不同字段的排列進行排序,也能夠按照升序,降序排序。比如下面的語句。
          order by field1 asc, field2 asc, field3 desc。

          這個排序條件按照field1的升序,field2的升序,field3的降序排序。
          注意,排在前面的字段具有較高的優先級。
          比如,兩條紀錄A和B,滿足如下條件:(1)A.field1 > B.field1,(2)A.field2 < B.field2。
          這時如果按照order by field1, field2語句排序,那么 A > B。
          如果上述條件中的(1)A.field1 > B.field1變化為A.field1 == B.field1。這時,條件(2)就會起作用。這時,A < B。

          我們來看看在Java中如何實現這種靈活而強大的排序。
          我們還是以上一節的Record類為例。Record類有3個字段,我們來看一看,有多少種可能的排序條件。
          (1)按field1排序。(2)按field2排序。(3)按field3排序。(4)按field1,field2排序。(5)按field1升序,按field2降序排序…...

          各種排序條件的排列組合,大概共有30種。而且,隨著字段個數的增長,排序條件的個數呈冪級數的增長。
          按照上一節的sort和Comparator方法,如果我們需要達到按照任意條件進行排序的目的,那么我們需要為每一個排序條件提供一個Comparator,我們需要30個Comparator類。
          當然,我們不會這么做,我們能夠進一步提取這個問題中的相同重復部分,優化我們的解決方案。

          3.2 問題分析
          我們來分析這個問題中變化的部分和不變的部分。
          上面所有的排序條件中,不變的部分有3部分:(1)A.field1和B.field1的比較,(2)A.field2和B.field2的比較,(3)A.field3和B.field3的比較;變化的部分有兩部分,(1)這三種比較條件的任意組合排列,(2)升序和降序。
          根據這段分析,我們引入兩個類,ReverseComparator類和CompositeComparator類。
          CompositeComparator類用來解決字段的組合排列問題。
          ReverseComparator類用來解決字段的升序、降序問題。

          3.3 ReverseComparator類的代碼

          java代碼:?


          import?java.util.Comparator;?

          public?class?ReverseComparator?implements?Comparator{?
          ??
          /**?the?original?comparator*/?
          ??
          private?Comparator?originalComparator?=?null;?

          ??
          /**?constructor?takes?a?comparator?as?parameter?*/?
          ??
          public?ReverseComparator(Comparator?comparator){?
          ????originalComparator?
          =?comparator;?
          ??}
          ?

          ??
          /**?reverse?the?result?of?the?original?comparator?*/?
          ??
          public?int?compare(Object?o1,?Object?o2){?
          ????
          return?-?originalComparator.compare(o1,?o2);?
          ??}
          ?
          }
          ?




          3.4 CompositeComparator類的代碼

          java代碼:?


          import?java.util.Comparator;?
          import?java.util.Iterator;?
          import?java.util.List;?
          import?java.util.LinkedList;?

          public?class?CompositeComparator?implements?Comparator{?
          ??
          /**?in?the?condition?list,?comparators'?priority?decrease?from?head?to?tail?*/?
          ??
          private?List?comparators?=?new?LinkedList();?

          ??
          /**?get?the?comparators,?you?can?manipulate?it?as?need.*/?
          ??
          public?List?getComparators(){?
          ????
          return?comparators;?
          ??}
          ?

          ??
          /**?add?a?batch?of?comparators?to?the?condition?list?*/?
          ??
          public?void?addComparators(Comparator[]?comparatorArray){?
          ????
          if(comparatorArray?==?null){?
          ??????
          return;?
          ????}
          ?

          ????
          for(int?i?=?0;?i?<?comparatorArray.length;?i++){?
          ??????comparators.add(comparatorArray);?
          ????}
          ?
          ??}
          ?

          ??
          /**?compare?by?the?priority?*/?
          ??
          public?int?compare(Object?o1,?Object?o2){?
          ????
          for(Iterator?iterator?=?comparators.iterator();?iterator.hasNext();){?
          ??????Comparator?comparator?
          =?(Comparator)iterator.next();?

          ??????
          int?result?=?comparator.compare(o1,?o2);?

          ??????
          if(result?!=?0){?
          ????????
          return?result;?
          ??????}
          ?
          ????}
          ?

          ????
          return?0;?
          ??}
          ?
          }
          ?




          3.5 Comparator的組合應用
          這一節講述上面兩個類的用法。
          對應前面的排序問題,我們只需要3個Comparator類:
          (1)Field1Comaprator;
          (2)Field2Comaprator;
          (3)Field3Comaprator。

          下面舉例說明,如何組合這些Comparator實現不同的排序條件。
          (1)order by field1, field2

          java代碼:?


          CompoiComparator?myComparator?=?new?CompoiComparator();?
          myComparator.?addComparators(?
          new?Comparator[]{new?Field1Comaprator?(),??new?Field2Comaprator?()};?
          );?

          //?records?is?a?list?of?Record?
          Collections.sort(records,??myComparator);?





          (2)order by field1 desc, field2

          java代碼:?


          CompoiComparator?myComparator?=?new?CompoiComparator();?
          myComparator.?addComparators(?
          new?Comparator[]{?
          new?ReverseComparator(new?Field1Comaprator?()),??
          new?Field2Comaprator?()}
          ;?
          );?

          //?records?is?a?list?of?Record?
          Collections.sort(records,??myComparator);?





          這里提供的ReverseComparator類和CompositeComparator類都采用了Decorator Pattern。
          CompositeComparator類同時也是Composite Pattern。

          4.過濾條件的排列組合
          (多謝shinwell指正,我改正了后面的代碼)

          過濾條件問題也屬于條件組合問題的范疇。比如JDK提供的java.io.File類提供了一個文件過濾方法listFile(FileFilter),用戶可以定制不同的FileFilter,實現不同的過濾條件,比如文件時間在某個范圍內;文件后綴名,文件名符合某種模式;是目錄,還是文件,等等。
          同樣,我們可以應用上述的解決方法,實現靈活的過濾條件組合——用一個CompositeFilter類任意組合過濾條件,用一個ReverseFilter類作為排除條件。
          4.1 CompositeFilter類的代碼

          java代碼:?


          import?java.io.FileFilter;?
          import?java.io.File;?

          import?java.util.Iterator;?
          import?java.util.List;?
          import?java.util.LinkedList;?

          public?class?CompositeFilter?implements?FileFilter?{?

          ??
          /**?in?the?filter?list,?every?condition?should?be?met.?*/?
          ??
          private?List?filters?=?new?LinkedList();?

          ??
          /**?get?the?filters,?you?can?manipulate?it?as?need.*/?
          ??
          public?List?getFilters(){?
          ????
          return?filters;?
          ??}
          ?

          ??
          /**?add?a?batch?of?filters?to?the?condition?list?*/?
          ??
          public?void?addFilters(FileFilter[]?filterArray){?
          ????
          if(filterArray?==?null){?
          ??????
          return;?
          ????}
          ?

          ????
          for(int?i?=?0;?i?<?filterArray.length;?i++){?
          ??????filters.add(filterArray);?
          ????}
          ?
          ??}
          ?

          ??
          /**?must?meet?all?the?filter?condition?*/?
          ??
          public?boolean?accept(File?pathname)?{?
          ????
          for(Iterator?iterator?=?filters.iterator();?iterator.hasNext();){?
          ??????FileFilter?filter?
          =?(FileFilter)iterator.next();?

          ??????
          boolean?result?=?filter.accept(pathname);?

          ??????
          //?if?any?condition?can?not?be?met,?return?false.?
          ??????if(result?==?false){?
          ????????
          return?false;?
          ??????}
          ?
          ????}
          ?

          ????
          //?all?conditions?are?met,?return?true.?
          ????return?true;?
          ??}
          ?
          }
          ?




          4.2 ReverseFilter類的代碼
          java代碼:?


          import?java.io.FileFilter;?
          import?java.io.File;?

          public?class?ReverseFilter?implements?FileFilter?{?
          ??
          /**?the?original?filter*/?
          ??
          private?FileFilter?originalFilter?=?null;?

          ??
          /**?constructor?takes?a?filter?as?parameter?*/?
          ??
          public?ReverseFilter(FileFilter?filter){?
          ????originalFilter?
          =?filter;?
          ??}
          ?

          ??
          /**?must?meet?all?the?filter?condition?*/?
          ??
          public?boolean?accept(File?pathname)?{?
          ??????
          return?!originalFilter.accept(pathname);?
          ??}
          ?
          }
          ?




          5.總結
          本文講述了Design Pattern的分析和實踐,并闡述了一類條件組合問題的解決思路。
          posted on 2006-04-24 09:23 Long Long Ago 閱讀(437) 評論(0)  編輯  收藏 所屬分類: others
          主站蜘蛛池模板: 酒泉市| 安龙县| 巴南区| 湖口县| 海安县| 汾西县| 富阳市| 枣强县| 富裕县| 三亚市| 梁河县| 沁阳市| 西乡县| 佳木斯市| 宁远县| 贡觉县| 石家庄市| 固始县| 常山县| 定州市| 牡丹江市| 吉水县| 焉耆| 宜丰县| 鄄城县| 建昌县| 陇南市| 越西县| 泗阳县| 丰宁| 海晏县| 海城市| 莱阳市| 子长县| 浮梁县| 灵川县| 杨浦区| 桐乡市| 义马市| 八宿县| 类乌齐县|