The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

          #

          說到現在,讀者應該對Comparable接口有了大概的了解,但是為什么又要有一個Comparator接口呢?難道Java的開發者都吃飽撐著沒事做嗎?

          再談Comparator接口之前,大家應該先了解一個叫“策略模式”的東東。一下是百度百科對策略模式的描寫:

          策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。(原文:The Strategy Pattern defines a family of algorithms,encapsulates each one,and makes them interchangeable. Strategy lets the algorithm vary independently from clients that use it.)

           

          之所以要談到策略模式,就是因為Comparator接口其實就是一種策略模式的實踐。實現Comparator接口的類必然就會實現一個compareTo(Object o1, Object o2)的方法,而這個方法就是算法中的一部分,所有使用了compareTo方法的類都不會關心compareTo是如何工作的,只關心他的返回值,這也是面向對象中著名的封裝特性。

          那Comparator接口應該如何使用呢?別急,首先我們要先對Person類進行一下處理,因為我們現在使用Comparator接口,所以Comparable接口就可以光榮的退休了:

             1: public class Person {
             2:  
             3:     private String name;
             4:     private int age;
             5:     
             6:     public Person() {
             7:         
             8:     }
             9:     
            10:     public Person(String name, int age) {
            11:         this.name = name;
            12:         this.age = age;
            13:     }
            14:  
            15:     public String getName() {
            16:         return name;
            17:     }
            18:  
            19:     public void setName(String name) {
            20:         this.name = name;
            21:     }
            22:  
            23:     public int getAge() {
            24:         return age;
            25:     }
            26:  
            27:     public void setAge(int age) {
            28:         this.age = age;
            29:     }
            30:  
            31:     @Override
            32:     public String toString() {
            33:         return "Person [age=" + age + ", name=" + name + "]";
            34:     }
            35:  
            36: }

          新建一個實現Comparator的實現類PersonComparator:

             1: import java.util.Comparator;
             2:  
             3: public class PersonComparator implements Comparator<Person> {
             4:  
             5:     @Override
             6:     public int compare(Person p1, Person p2) {
             7:         if (p1.getAge() > p2.getAge()) {
             8:             return 1;
             9:         } else if (p1.getAge() < p2.getAge()) {
            10:             return -1;
            11:         }
            12:         return 0;
            13:     }
            14:     
            15: }

          然后再用回我們的CompareTest做測試:

             1: import java.util.Arrays;
             2:  
             3: public class CompareTest {
             4:  
             5:     public static void main(String[] args) {
             6:         Person[] persons = {
             7:                 new Person("P1", 60),
             8:                 new Person("P2", 20),
             9:                 new Person("P3", 40)
            10:         };
            11:         
            12:         System.out.println(Arrays.toString(persons));
            13:         
            14:         Arrays.sort(persons, new PersonComparator());
            15:         
            16:         System.out.println(Arrays.toString(persons));
            17:     }
            18:  
            19: }

          注意:在上面的sort方法中,我們傳進了一個PersonComparator的實例對象作為參數,讀者也可以試試不傳入這個參數,看是否能正確工作。

          結果當然是跟上面演示的例子一樣啦,我就不再重復了。

          posted @ 2011-04-12 12:26 Eric_jiang 閱讀(3590) | 評論 (0)編輯 收藏

          新建一個文本文檔,在其中輸入以下內容:
          DirectShowSource("E:\FreeLoop.wmv")
          LoadPlugin("C:\Program Files\Easy RealMedia Tools\common\VSFilter.dll")
          TextSub("E:\FreeLoop.srt")

          第1行是指定視頻文件路徑,你可以根據自己文件的具體位置進行修改。第2行是VobSub濾鏡插件的文件路徑,第3行是字幕文件的路徑,同樣根據具體位置修改。將文件保存為FreeLoop.avs,文件名任意,但擴展名必須是avs。
          第三步:啟動Easy RealMedia Producer,將彈出設置窗口,將“select language”設置為“簡體中文”,點擊“確定”進入軟件主界面。單擊“添加”按鈕,添加上面保存的FreeLoop.avs。


          第四步:雙擊任務出現RealMedia編碼設置窗口,按需設置好音視頻碼率,下面可以輸入剪輯信息,輸入好后點擊“確定”返回主界面。
          第五步:最后點擊左下角的“開始壓縮”,等待壓縮完成即可。完成后打開壓縮好的FreeLoop.rmvb文件,就可以看到帶有字幕的MV了!用這種方法添加字幕,簡單方便,而且支持文件類型眾多,事實上很多電影添加字幕也是這樣壓制成的。

          posted @ 2011-02-17 13:09 Eric_jiang 閱讀(944) | 評論 (1)編輯 收藏

          import java.io.*; 
          public class ClassVersionChecker { 
          public static void main(String[] args) throws IOException { 
             
          for (int i = 0; i < args.length; i++) 
                  checkClassVersion
          (args[i]); 
          } 
           
             
          private static void checkClassVersion(String filename) 
                 
          throws IOException 
             
          { 
                 
          DataInputStream in = new DataInputStream 
                   
          (new FileInputStream(filename)); 
           
                 
          int magic = in.readInt(); 
                 
          if(magic != 0xcafebabe) { 
                   
          System.out.println(filename + " is not a valid class!");; 
                 
          } 
                 
          int minor = in.readUnsignedShort(); 
                 
          int major = in.readUnsignedShort(); 
                 
          System.out.println(filename + ": " + major + " . " + minor); 
                 
          in.close(); 
             
          } 
          } 

          The possible values are :

          major  minor Java platform version  
          45       3           1.0 
          45       3           1.1 
          46       0           1.2 
          47       0           1.3 
          48       0           1.4 
          49       0           1.5 
          50       0           1.6 
          posted @ 2010-12-10 17:42 Eric_jiang 閱讀(267) | 評論 (3)編輯 收藏

          import java.io.FileInputStream;

          public class JavaVersionUtil {

           private static final String str = "C://a.class";
           // 版本號對應:
           // 5.0
           // 版本號(version):49.0
           // 6.0
           // 版本號(version):50.0
           // 1.4
           // 版本號(version):46.0
           // 1.3
           // 版本號(version):45.3

           public static void main(String args[]) {
            try {
             // 讀取文件數據,文件是當前目錄下的First.class
             FileInputStream fis = new FileInputStream(str);
             int length = fis.available();
             // 文件數據
             byte[] data = new byte[length];
             // 讀取文件到字節數組
             fis.read(data);
             // 關閉文件
             fis.close();
             // 解析文件數據
             parseFile(data);
            } catch (Exception e) {
             System.out.println(e);
            }
           }

           private static void parseFile(byte[] data) {
            // 輸出魔數
            System.out.print("魔數(magic):0x");
            System.out.print(Integer.toHexString(data[0]).substring(6)
              .toUpperCase());
            System.out.print(Integer.toHexString(data[1]).substring(6)
              .toUpperCase());
            System.out.print(Integer.toHexString(data[2]).substring(6)
              .toUpperCase());
            System.out.println(Integer.toHexString(data[3]).substring(6)
              .toUpperCase());
            // 主版本號和次版本號碼
            int minor_version = (((int) data[4]) << 8) + data[5];
            int major_version = (((int) data[6]) << 8) + data[7];
            System.out.println("版本號(version):" + major_version + "."
              + minor_version);
           }

          }

          posted @ 2010-11-11 13:12 Eric_jiang 閱讀(652) | 評論 (0)編輯 收藏

          一個java的class文件是一個二進制文件,其中前四個字節是magic位,第五到第六個字節對應于minor和major,下面是這個類文件版本與JDK的對應關系。class文件的minor和major可以通過ultraedit來查看,或自己編程等。
          major minor Java platform version
          45 3 1.0
          45 3 1.1
          46 0 1.2
          47 0 1.3
          48 0 1.4
          49 0 1.5
          50 0 1.6
          posted @ 2010-11-11 13:11 Eric_jiang 閱讀(811) | 評論 (0)編輯 收藏

          一直在tomcat服務器上做開發,客戶要求部署到TongWeb服務器上,并且要求JDK版本為1.4.2。把WEB應用部署到TongWeb上,本來在tomcat正常的運行的程序在TongWeb上出現了java.lang.UnsupportedClassVersionError異常。

          TongWeb的JSP容器也是Tomcat呀。應該不會出現這樣的問題。原因是什么呢?G一下。找到了原因。總結如下:

          出現java.lang.UnsupportedClassVersionError 錯誤的原因,是因為我們使用高版本的JDK編譯的Java class文件試圖在較低版本的JVM上運行,所報的錯誤。

          因為,高版本的JDK生成的class文件使用的格式,可能與低版本的JDK的.class文件格式不同。這樣,低版本的JVM無法解釋執行這個.class文件,會拋出java.lang.UnsupportedClassVersionError不支持的Class版本錯誤。

          這個錯誤尤其在JDK5與JDK5之前的版本上表現明顯。因為,JDK5在Java語法上作了不少增強,引入了一些新的.class文件的元素,導致舊版本的JVM無法解釋、執行.class文件。即使這個類并沒有使用任何JDK5的新元素,但是JDK5生成的.class文件,JDK1.4及其以前的JVM都無法辨認!

          所以,目前使用最廣的,還是JDK1.4。很多軟件和項目都無法使用JDK5。

          有一個名叫 Toby Reyelts 的開發人員決定消除 JDK 5.0 編譯器限制。結果就是開放源代碼的 Retroweaver 項目(參見 參考資料)。Retroweaver 使用 classworking 技術來修改由 JDK 5.0 編譯器生成的二進制類表示,以便這些類可以與早期的 JVM 一起使用。

          它通過修改JDK5生成的.class文件,將其變為JVM1.4及之前版本能夠運行的.class文件。

          目前,使用新版本的IDE編譯程序可能會造成你遭遇java.lang.UnsupportedClassVersionError 錯誤。

          比如,Eclipse3.3+MyEclipse6.5這個新版的IDE工具。進入首選項---Java---編譯器,可以看到,默認的編譯器依從等級是5.0,這里改為1.4,因為我們使用的軟件需要運行在JDK1.4的JVM上。

          步驟:項目點右鍵-->Properties-->Java Compiler-->將Enable project specific settings前的勾去掉-->Compiler compiliance level選擇你想要的版本

          在MyEclipse----應用服務器下,指定Tomcat5。指定Tomcat使用jdk1.4。

          這樣,就全部指定使用Jdk1.4來編譯和運行程序了。如果全部指定jdk5也是可以的。但是,絕對不能夠使用jdk5編譯程序,而又在jdk1.4上運行程序,那樣將會拋出java.lang.UnsupportedClassVersionError不支持的Class版本錯誤。反之,則可以。

          這種情況下,不論是Eclipse生成的war包,還是ant文件生成war包,都使用jdk5編譯,就會在運行時出現錯誤,該應用程序將無法啟動。如果你查看Tomcat的日志文件,將會看到正是java.lang.UnsupportedClassVersionError錯誤發生了!

          經驗:以后做開發,如果可能的話,盡量使用JDK1.4,1.5來編譯源程序,不要使用JDK過高版本的特性,以保持較好的移植性和兼容性。

           

          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/xiaojianpitt/archive/2008/09/11/2913094.aspx

          posted @ 2010-11-11 11:16 Eric_jiang 閱讀(945) | 評論 (0)編輯 收藏

          WebLogic Server 8,9,10破解補丁下載

          WebLogic Server

                 Server 是一個很優秀的商業中間件,但是價格昂貴!!!

                 其實從官網下載下來WebLogic Server 是全功能版的,但是有5個IP的限制,也就是說只能有5以下的
          今天無意中找到了破解這個限制的補丁,很全,8,9,10都有,很爽吧!!!破解的方法在壓縮包中的readme.txt,參照上面的操作就可以了,我已經試驗過8的的確有效,哪位兄弟有條件的可以幫我測試一下9和10是否有效。

                weblogic.8.1.crack.rar

                weblogic.9.2.crack.zip

                weblogic.10.crack.zip

               請參照readme.txt中的破解說明!!!
          weblogic 10.0破解版使用說明:
          今天看了一下版本10,算法沒變,只是驗證文件位置變了,老方法,測試了一下,OK!!!
          1.將license.bea和weblog_crack.jar拷貝到bea安裝目錄下,例如d:\bea
          2.修改d:\bea\user_projects\domains\odpsdomain(你建立的域)\bin\startWeblogic.cmd
          修改
          set CLASSPATH=%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSP

          set CLASSPATH=d:\bea\weblogic_crack.jar;%CLASSPATH%;%MEDREC_WEBLOGIC_CLASSP
          3. 重啟weblogic

          另附weblogic 10的下載地址

          http://download2.bea.com/pub/platform/100/server100_win32.exe


          posted @ 2010-11-01 22:55 Eric_jiang 閱讀(1375) | 評論 (0)編輯 收藏

          具體元素的接口與實現類

          public interface Person {
                void accept(Visitor visitor);
          }


          public class Woman implements Person{

              public void accept(Visitor visitor) {
                    visitor.visit(this);
              }
          }


          public class Man implements Person{

              public void accept(Visitor visitor) {
                  visitor.visit(this);
              }
          }



          訪問者接口與實現類,分別代表男人與女人在不同的狀態下的表現

          public interface Visitor {
                public void visit(Man man);
                public void visit(Woman girl);
          }

          //成功時Man與Woman的不同表現
          public class Success implements Visitor{

              public void visit(Man man) {
                  System.out.println("當男人成功時,背后多半有一個偉大的女人");
              }


              public void visit(Woman woman) {
                  System.out.println("當女人成功時,背后大多有一個不成功的男人");
              }
          }

          //戀愛時Man與Woman的不同表現
          public class Love implements Visitor{

              public void visit(Man man) {
                  System.out.println("當男人戀愛時,凡事不懂也裝懂");
              }


              public void visit(Woman girl) {
                  System.out.println("當女人戀愛時,遇事懂也裝不懂");
              }
          }



          ObjectStructure與客戶端測試代碼

          import java.util.*;

          public class ObjectStructure {
              private List<Person> elements = new ArrayList<Person>();

              public void attach(Person element){
                  elements.add(element);
              }
             
              public void detach(Person element){
                  elements.remove(elements);
              }
             
              //遍歷各種具體元素并執行他們的accept方法
              public void display(Visitor visitor){
                  for(Person p:elements){
                      p.accept(visitor);
                  }
              }
          }


          public class Client {
                public static void main(String[] args) {
                  ObjectStructure o = new ObjectStructure();  //依賴于ObjectStructure
                  //實例化具體元素
                  o.attach(new Man()); 
                  o.attach(new Woman());
                 
                  //當成功時不同元素的不同反映
                  Visitor success = new Success();           //依賴于抽象的Visitor接口
                  o.display(success);
                 
                  //當戀愛時的不同反映
                  Visitor amativeness = new Love();          //依賴于抽象的Visitor接口
                  o.display(amativeness);
                 
              }
          }



          需求的變化

          假設現在需求要擴展數據結構,增加一種具體元素,男與女之外的一種不明物體,我們暫時把它稱為“怪獸”,在既有訪問者模式的架構下,應該怎樣?首先增加一個Bruce類,實現Person接口。最麻煩的是要修改訪問者接口及其所有具體訪問者!

            因為Visit方法中沒有包含訪問Bruce對象的行為,因此我們被迫要去手工更改Visitor(包括抽象的,具體的),在其中添加有關Bruce對象的行為,這嚴重違反了“開放-封閉”原則。究其原因在于目前的結構下,被訪問對象與訪問對象互相依賴,自然不利于分離變化,必須去掉一層依賴關系。

          我們嘗試把Visitor對Person(元素)的依賴關系去掉,抽象出對應每個具體元素的ElementVisitor接口 -->ManVisitor,WomanVisitor,然后把Visitor對Person的依賴關系轉移到ManVisitor與 WomanVisitor身上。
           
          現在Visitor接口已經沒有任何抽象方法,只是一個空接口,每一個具體元素對應有一個ElementVisitor接口,每一個元素對應的ElementVisitor接口有訪問該元素的visit(),相當把原來在Visitor接口中聲明工作,交由各個具體ElementVisitor接口完成。


          經過改造后的代碼:
          原Visitor接口

          public interface Visitor {
                //退化到沒有任何抽象方法
          }



          新增加ManVisitor,WomanVisitor接口

          public interface ManVisitor {
                public void visit(Man man);
          }

          public interface WomanVisitor {
                public void visit(Woman w);
          }

           
          具體Visitor實現類現在同時實現3個接口

          //由實現Visitor接口擴展成實現Visitor,WomanVisitor,ManVisitor三個接口
          public class Success implements Visitor,WomanVisitor,ManVisitor{

              public void visit(Man man) {
                  System.out.println("當男人成功時,背后多半有一個偉大的女人");
              }

              public void visit(Woman girl) {
                  System.out.println("當女人成功時,背后大多有一個不成功的男人");
              }
          }


          //由實現Visitor接口擴展成實現Visitor,WomanVisitor,ManVisitor三個接口
          public class Love implements Visitor,WomanVisitor,ManVisitor{

              public void visit(Man man) {
                  System.out.println("當男人戀愛時,凡事不懂也裝懂");
              }

              public void visit(Woman girl) {
                  System.out.println("當女人戀愛時,遇事懂也裝不懂");
              }
          }



          Person接口沒有變化,依舊只依賴于Visitor接口

          public interface Person {
                void accept(Visitor visitor);
          }



          改造后的具體元素類Man與Woman

          public class Man implements Person {

              // 先對visitor進行類型轉換,再執行visit方法,因為Visitor接口已經沒有聲明任何抽象方法了
              public void accept(Visitor visitor) {
                  if (visitor instanceof ManVisitor) {
                      ManVisitor mv = (ManVisitor) visitor;
                      mv.visit(this);
                  }
              }
          }


          public class Woman implements Person {

              // 先對visitor進行類型轉換,再執行visit方法,因為Visitor接口已經沒有聲明任何抽象方法了
              public void accept(Visitor visitor) {
                  if (visitor instanceof WomanVisitor) {
                      WomanVisitor wv = (WomanVisitor) visitor;
                      wv.visit(this);
                  }
              }
          }



          ObjectStructure與客戶端測試代碼沒有變化

          import java.util.*;

          public class ObjectStructure {
              private List<Person> elements = new ArrayList<Person>();

              public void attach(Person element){
                  elements.add(element);
              }
             
              public void detach(Person element){
                  elements.remove(elements);
              }
             
              //遍歷各種具體元素并執行他們的accept方法
              public void display(Visitor visitor){
                  for(Person p:elements){
                      p.accept(visitor);
                  }
              }
          }


          public class Client {
                public static void main(String[] args) {
                  ObjectStructure o = new ObjectStructure();  //依賴于ObjectStructure
                  //實例化具體元素
                  o.attach(new Man()); 
                  o.attach(new Woman());
                 
                  //當成功時不同元素的不同反映
                  Visitor success = new Success();           //依賴于抽象的Visitor接口
                  o.display(success);
                 
                  //當戀愛時的不同反映
                  Visitor amativeness = new Love();          //依賴于抽象的Visitor接口
                  o.display(amativeness);       
              }
          }



          至此改造完畢!我們執行客戶端測試代碼,結果顯示:
          當男人成功時,背后多半有一個偉大的女人
          當女人成功時,背后大多有一個不成功的男人
          當男人戀愛時,凡事不懂也裝懂
          當女人戀愛時,遇事懂也裝不懂

          此時,客戶端仍然只依賴于Visitor空接口與ObjectStructure類。可能一開始大家會認為空接口沒有什么用,現在就能體現出他的威力了,使客戶端與具體Visitor的高度解耦!也正是這種思維的核心在JavaAPI中也有類似的應用,這種空接口被稱為標識接口。比如java.io.Serializable與java.rmi.Remote等,標識接口里沒有任何方法和屬性,標識不對實現接口不對實現它的類有任何語義上的要求,它僅僅是表明實現它的類屬于一種特定的類型。
          上面具體訪問者實現的多個接口被稱為混合類型。這個概念《Java與模式》中有提及過:當一個具體類處于一個類的等級結構之中的時候,為這個具體類定義一個混合類型是可以保證基于這個類型的可插入性的關鍵。

          =================================無敵分界線====================================

          講了這么長,現在我們測試下改造后的訪問者模式
          首先增加一種行為(狀態),即原訪問者模式的優點

          增加一個具體訪問者Fail,修改一下客戶端測試代碼

          public class Fail implements Visitor,ManVisitor,WomanVisitor{

              public void visit(Man man) {
                  System.out.println("當男人失敗時,悶頭喝酒,誰也不用勸");
              }

              public void visit(Woman woman) {
                  System.out.println("當女人失敗時,眼淚汪汪,誰也勸不了");
              }
          }



          public class Client {
                public static void main(String[] args) {
                  ObjectStructure o = new ObjectStructure();  //依賴于ObjectStructure
                  //實例化具體元素
                  o.attach(new Man()); 
                  o.attach(new Woman());
                 
                  //當成功時不同元素的不同反映
                  Visitor success = new Success();           //依賴于抽象的Visitor接口
                  o.display(success);
                  System.out.println();
                 
                  //當戀愛時的不同反映
                  Visitor amativeness = new Love();          //依賴于抽象的Visitor接口
                  o.display(amativeness);       
                  System.out.println();
                 
                  //新增加失敗時的不同反映
                  Visitor fail = new Fail();
                  o.display(fail);
              }
          }



          結果顯示:
          當男人成功時,背后多半有一個偉大的女人
          當女人成功時,背后大多有一個不成功的男人

          當男人戀愛時,凡事不懂也裝懂
          當女人戀愛時,遇事懂也裝不懂

          當男人失敗時,悶頭喝酒,誰也不用勸
          當女人失敗時,眼淚汪汪,誰也勸不了



          增加新的行為(狀態)與原來一樣方便!只需要增加一個具體訪問者即可!
          現在我們來增加一個具體元素(正是寫這篇文章的初衷)

          首先增加一個具體元素Bruce

          public class Bruce implements Person{
             
              public void accept(Visitor visitor) {       
                  if(visitor instanceof BruceVisitor){
                      BruceVisitor bv = (BruceVisitor) visitor;
                      bv.visit(this);
                  }
                  //這個else可寫可不寫
                  else{
                      String s = visitor.getClass().getName();
                      String state = s.substring(s.lastIndexOf(".")+1,s.length());
                      System.out.println("噢..原來怪獸在"+state+"的時候是沒有行為的!!");
                  }       
              }
          }


          //按照新的思維方式增加一個對應的ElementVisitor接口
          public interface BruceVisitor {
                public void visit(Bruce bruce);
          }



          我們讓Success這個具體訪問者多實現一個BruceVisitor訪問者接口,和修改一下客戶端代碼進行測試

          public class Success implements Visitor,WomanVisitor,ManVisitor,BruceVisitor{

              public void visit(Man man) {
                  System.out.println("當男人成功時,背后多半有一個偉大的女人");
              }

              public void visit(Woman girl) {
                  System.out.println("當女人成功時,背后大多有一個不成功的男人");
              }

              public void visit(Bruce bruce) {
                  System.out.println("當怪獸成功時.........無語..........");
              }
          }


          public class Client {
                public static void main(String[] args) {
                  ObjectStructure o = new ObjectStructure();  //依賴于ObjectStructure

                  o.attach(new Man()); 
                  o.attach(new Woman());
                  o.attach(new Bruce());      //新增一種具體元素Bruce
                 
                  Visitor success = new Success();           //依賴于抽象的Visitor接口
                  o.display(success);
                  System.out.println();
                 
                  Visitor amativeness = new Love();          //依賴于抽象的Visitor接口
                  o.display(amativeness);       
                  System.out.println();
                 
                  Visitor fail = new Fail();
                  o.display(fail);
              }
          }



          顯示結果:
          當男人成功時,背后多半有一個偉大的女人
          當女人成功時,背后大多有一個不成功的男人
          當怪獸成功時.........無語..........

          當男人戀愛時,凡事不懂也裝懂
          當女人戀愛時,遇事懂也裝不懂
          噢..原來怪獸在Love的時候是沒有行為的!!

          當男人失敗時,悶頭喝酒,誰也不用勸
          當女人失敗時,眼淚汪汪,誰也勸不了
          噢..原來怪獸在Fail的時候是沒有行為的!!


          這個結果你滿意嗎?
          雖然,這只是部分符合“開放-封閉”原則,我們不需要修改Visitor接口,但還是得去修改Success實現新的接口。但是修改具體類比修改接口的代價小得多,不需要重新編譯所有訪問接口和具體訪問者。使我們面對新的變化也容易得多。而且這還有一個好處,就是可以讓各種元素有選擇地讓別人訪問,如上述例子,這樣使訪問者模式的運用起來更加靈活。
          posted @ 2010-10-31 17:24 Eric_jiang 閱讀(407) | 評論 (0)編輯 收藏

          類適配器
          客戶的開發人員定義了一個接口,期望用這個接口來完成整數的求和操作,接口定義如下:
           
          public interface Operation{   
                public int add(int a,int b);   

           開發人員在了解這個接口的定義后,發現一個第三方類,里面有一個方法能實現他們期望的功能,其代碼如下:
           
          public class OtherOperation{   
                public int otherAdd(int a,int b){   
                     return a + b;   
                }   

           以上第三方類OtherOperation的方法public int otherAdd(int a,int b)所提供的功能,完全能符合客戶的期望,所以只需要想辦法把OtherOperation的otherAdd(int a,int b)和客戶的Operation接口聯系起來,讓這個第三方類來為客戶提供他們期望的服務就行了,這樣就避免了開發人員再度去研究類似OtherOperation的otherAdd(int a,int b)方法的實現(利用已有的輪子,避免重復發明),這方法之一,就是用適配器模式:
           
          public class AdapterOperation extends OtherOperation implements Operation{   
                public int add(int a,int b){   
                     return otherAdd(a,b);   
                }   

           以上就是適配器的實現方法之一,類適配器,在以上實現中存在著三中角色分別是:
          1:適配目標角色:Operation。
          2:適配類(原)角色:OtherOperation。
          3:適配器角色:AdapterOperation。
          其中適配器角色是適配器模式的核心。
          適配器的主要工作就是通過封裝現有的功能,使他滿足需要的接口。
          對象適配器
          我們再來看看另一種情況:
          假如客戶接口期望的功能不止一個,而是多個:
           
          public interface Operation{   
                public int add(int a,int b);   
                public int minus(int a,int b);   
                public int multiplied(int a,int b);   

           而能提供這些實現的原可能不止一個:
           
          public class OtherAdd{   
                public int otherAdd(int a,int b){   
                     return a + b;   
                }   
          }   
            
          public class OtherMinus{   
                public int minus(int a,int b){   
                     return a - b;   
                }   
          }   
            
          public class OtherMultiplied{   
                public int multiplied(int a,int b){   
                     return a * b;   
                }   

           由于java是不能實現多繼承的,所以我們不能通過構建一個適配器,讓他來繼承所有原以完成我們的期望,這時候怎么辦呢?只能用適配器的另一種實現--對象適配器:
           
          public class AdapterOperation implements Operation{   
                private OtherAdd add;   
                private OtherMinus minus;   
                private OtherMultiplied multiplied;   
            
                public void setAdd(OtherAdd add){   
                      this.add = add;   
                }   
            
                public void setMinus(OtherMinus minus){   
                      this.minus = minus;   
                }   
            
                public void setMultiplied(OtherMultiplied multiplied){   
                      this.multiplied = multiplied;   
                }   
            
                //適配加法運算   
                public int add(int a,int b){   
                     return add.otherAdd(a,b);   
                }   
            
                //適配減法運算   
                public int minus(int a,int b){   
                    return minus.minus(a,b);   
                }   
            
                //適配乘法運算   
                public int multiplied(int a,int b){   
                   return multiplied.multiplied(a,b);   
                }   
          }
           
           

          上面代碼很明顯,適配器并不是通過繼承來獲取適配類(原)的功能的,而是通過適配類的對象來獲取的,這就解決了java不能多繼承所帶來的不便了。這也是java提倡的編程思想之一,即盡量使用聚合不要使用繼承。 還有一種情況是需要使用對象適配器的。我們來看看,單我們的客戶提供的需求并不是一個明確的接口,而是一個類,并沒有定義期望的方法,如下
           
          public class A{   
             public int add(int a,int b){   
                return a + b;   
             }   

           
          現在客戶要一個新類B,要求能在保留類A功能的情況下增加一個運算減法的功能,并要求B能隨時替換掉A但不能對已有系統造成影響。這樣我們只能新建一個類B,并讓B繼承A。
           
          public class B extends A{   
              b(){   
                super();   
              }   
            
              public int minus(int a,int b){   
                     //待實現的減法運算函數..   
              }   

           
          這時候,我們發現類C已經提供了實現減法的函數,
           
          public class C{
              public int minus(int a,int b){
                     return a - b;
              }
          }

          為了避免重復去設計該函數,我們決定引入C類,通過適配C類來達到我們的期望,但問題是A和C都是一個具體類,我們無法讓B同時繼承這個兩個類,而B繼承A又是必須的,所以我們只能考慮把C給內聚到B內部,對象適配器又得派上用場了。
           
          public class B extends A{
              private C c;
              B(){
                super();
              }
              public void setMinus(C c){
                   this.c= c;
              }
              public int minus(int a,int b){
                     return c.minus(a,b);
              }
          }

          這樣,在需要A類的地方都能用B類來代替,同時又保證了新的功能的引入。
          更靈活的實現--隱藏目標接口的抽象適配器
          做java 桌面應用的都知道WindowListener接口,
           
          public interface WindowListener extends EventListener{
           public void windowActivated(WindowEvent e);
           public void windowClosed(WindowEvent e);
           public void windowClosing(WindowEvent e);
           public void windowDeactivated(WindowEvent e);
           public void windowDeiconified(WindowEvent e);
           public void windowIconified(WindowEvent e);
           public void windowOpened(WindowEvent e);
          }

          要實現這個接口,我們就必須實現它所定義的所有方法,但是實際上,我們很少需要同時用到所有的方法,我們要的只是其中的兩三個。為了不使我們實現多余的方法,
          jdk WindowListener提供了一個WindowListener的默認實現類WindowAdapter類,這是一個抽象類,
           
          public abstract class WindowAdapter implements WindowListener{
           public void windowActivated(WindowEvent e){}
           public void windowClosed(WindowEvent e){}
           public void windowClosing(WindowEvent e){}
           public void windowDeactivated(WindowEvent e){}
           public void windowDeiconified(WindowEvent e){}
           public void windowIconified(WindowEvent e){}
           public void windowOpened(WindowEvent e){}
          }

          WindowAdapter類對WindowListener接口的所有有方法都提供了空實現,
          有了WindowAdapter類,我們只需要去繼承WindowAdapter,然后選擇我們所關心的方法來實現就行了,這樣就避免了直接去實現WindowListener接口。

          posted @ 2010-10-29 20:56 Eric_jiang 閱讀(319) | 評論 (0)編輯 收藏

          核心:要使window.close在Firefox中有效,必須先設置window.open

          對于最常用的關閉窗口鏈接,都比較熟悉,使用的Javascript函數就是:window.close(),寫完后在IE下測試,完全搞定;當你用Mozilla內核的瀏覽器打開時,點擊關閉窗口按鈕,你會發現事件并不會像你想象的那么順利,窗口根本就是無動于衷(真痛恨瀏覽器的兼容性吧,哈哈,淡定,沒有瀏覽器的兼容性,又怎么會有前端開發這個職業呢),這并不是Mozilla內核瀏覽器不支持window.close()這個方法(打開W3CSCHOOL,你會發現在Firefox 1.0就已經支持了),那到底是什么原因引起Firefox沒有執行這段代碼呢(準確地說應該是執行了,但沒有產生預期的效果而已,本人一直堅信:就目前這技術,機器是不會騙人的,一切還是人為原因)?

          經過Google一翻,在一篇名為:在Firefox 2.0中無法用Javascript關閉父窗口(原名:Cannot close parent window using javascript in Firefox 2.0)中找到真正的原因,其中有個網友直接使用下面的代碼的(問題是:Firefox 2.0以下執行,但2.0無效):

          function closeWindow() {
          window.open('','_parent','');
          window.close();
          }
          

          一位很了解這個問題的網友給出講解并貼出了原因:它當然不會關閉,如果在window.open方法中不添加URL參數照樣執行,但是下面的一行并不會執行或不會做任何事情。下面的稍微變化的代碼指出的close()方法常見的錯誤―close()方法不能關閉非Javascript腳本打開的窗口(原文:Yes, that doesn’t do anything. If I change the missing URL in the window.open command to an actual page, it executes but then the next line doesn’t run or doesn’t do anything. The following variation gives the usual script error for the close() method in this scenario — can’t close a window not opened by a script):

          function closeWindow() {
          newwin = window.open(location.href,'_parent','');
          newwin.close();
          }
          

          如果你使用window.open打開一個窗口,這時你才可以使用window.close去關閉它,相反如果你通過常規鏈接打開的窗口,window.close根本就關閉不了它,需要額外的用戶權限;這比直接使用關閉按鈕更令人討厭…(原文:If you launch the initial Firefox window using window.open, then window.close should work on it. However, if it is launched from a regular URL, then as you know it doesn’t work. There is a way to ask the user for extra permissions. However, that might be more annoying than leaving the window open…),原來上面的兩段代碼都只針對使用window.open打開的窗口,才能執行window.close關閉,而對于URL鏈接新開的窗口,必須要額外的用戶權限(UniversalBrowserWrite privilege),其實只要在執行關閉窗口之前加上:

          netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
          

          這段代碼即可,具體說明參見Mozilla官網的“如何使用擴展權限”(Using Expanded Privileges)

          posted @ 2010-10-19 13:08 Eric_jiang 閱讀(2864) | 評論 (0)編輯 收藏

          僅列出標題
          共57頁: First 上一頁 41 42 43 44 45 46 47 48 49 下一頁 Last 
          主站蜘蛛池模板: 崇信县| 南华县| 漳平市| 榆林市| 辽宁省| 泾阳县| 宁海县| 麻江县| 驻马店市| 溧水县| 富阳市| 谢通门县| 西城区| 星座| 陵川县| 盐池县| 荃湾区| 宁强县| 巴中市| 漯河市| 突泉县| 土默特右旗| 嵩明县| 遂平县| 额济纳旗| 葵青区| 周口市| 泽州县| 吉首市| 清原| 鞍山市| 莒南县| 隆德县| 宝应县| 四川省| 石嘴山市| 普陀区| 濮阳县| 通渭县| 太白县| 刚察县|