回歸

          驀然回首,那人卻在燈火闌珊處

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            4 Posts :: 2 Stories :: 12 Comments :: 0 Trackbacks

          2007年6月8日 #

           

                   前些時工作忙,中間停頓一段時間,今天繼續。向關注這里的文章的博友們表示抱歉。
                   今天說說一個簡單的模式,迭代器模式(Iterator),他屬于行為模式中的一種。

                   [形成]

                   在Java程序中,在輸出List類型的對象時候,出現最多的程式塊就是:
                   

          1     for (int i = 0 ;i<list.size; i++){
          2         XXX x = (XXX)list.get(i);
          3     }

           

          其中list 是List 類型,里邊放著若干個XXX類型的對象。
          這種 方式是采用i++遞增的方式來遍歷list中的所有對象來進行相關操作。對于設計模式,把i的功能抽象劃的結果就是:Iterator Pattern

          Iterate 中文的意思是“迭代,反復”,Iterator 的意思可以理解為“迭代器”。

                 [代碼示例]
                  示例程式是把書(Book)放到書架上(BookShelf)上,并依次輸出書名。
                   
                   程式列表
             
          名稱 說明
          Aggregate 表示已聚合的接口
          Iterator 執行遞增,遍歷的接口
          Book 表示書籍的類
          BookShelf 表示書架的類
          BookShelfIterator 掃描書架的類
          Main 測試用的類

             
                    










          [UML圖]






                [示例代碼和類的詮釋]

          1 package Iterator;
          2 
          3 import java.util.Iterator;
          4 
          5 public interface Aggregate {
          6     public abstract Iterator iterator();
          7 }
          8 

          Aggregate 接口:
               該接口只聲明了一個方法,建立一個可以對應聚合的Iterator.,當需要遍歷某個聚合對象時,調用Iterator方法可以建立一個實現Iterator接口的類的對象實例。

          1 package Iterator;
          2 
          3 public interface Iterator {
          4     public abstract boolean hasNext();
          5     public abstract Object next();
          6 }
          7 

          Iterator 接口:
          這是該模式的核心接口,Iterator接口執行元素的遞增,具有循環遍歷的功能。Iterator的接口的方法因需要而定,我們可以初步確定接口方法:
          hasNext() :是檢查有沒有“下一個元素”,返回boolean.(有,返回true,,無,返回false)
          next();取得“下一個元素”,同時把取對象的指針指向下一個元素,以便下次調用next方法的時候確實能取到下一個元素。這些具體實現還得看具體的實現Iterator接口的類的實現才知道

           1 package Iterator;
           2 
           3 public class Book {
           4     private String name = "";
           5 
           6     public Book(String name) {
           7         this.name = name;
           8     }
           9 
          10     public String getName() {
          11         return name;
          12     }
          13 }
          14 

          Book 類:
          表示書籍的類,比較簡單,通過getName方法得到書的名字,書名是以構造函數初始化對象的時候用參數來字號定。


           1 package Iterator;
           2 
           3 public class BookShelf implements Aggregate{
           4     private Book[] books;
           5     private int last = 0;
           6     
           7     public BookShelf(int maxsize){
           8         this.books = new Book[maxsize];
           9     }
          10         
          11     public Book getBookAt(int index){
          12         return books[index];
          13     }
          14     public void appendBook(Book book){
          15         this.books[last] = book;
          16         last++;
          17     }
          18     
          19     public int getLength(){
          20         return last;
          21     }
          22     public Iterator iterator(){
          23         return new BookShelfIterator(this);
          24     }
          25 }
          26 


          BookShelfl類:
               該類是表現書架作用的類,保證實現Aggregate接口所聲明的Iterator方法里返回實現Iterator接口的實例。如果需要遍歷書架上的書,調用iterator方法。books數組存放的對象就是book,書架大小可以在一開始建立時設置大小,當然我們可以不用數組而采用java.util.Vector,就可以往書架上放超過指定數量的書籍。


           1 package Iterator;
           2 
           3 public class BookShelfIterator implements Iterator{
           4     private BookShelf bookShelf;
           5     private int index;
           6     public BookShelfIterator(BookShelf bookShelf){
           7         this.bookShelf = bookShelf;
           8         this.index =0;
           9     }
          10     
          11     public boolean hasNext(){
          12         if(index < bookShelf.getLength()){
          13             return true;
          14         }else{
          15             return false;
          16         }
          17     }
          18     
          19     public Object next(){
          20         Book book = bookShelf.getBookAt(index);
          21         index++;
          22         return book;
          23     }
          24 
          25 }
          26 

          BookShelfIterator類:

                字段bookShelf指定BookShelfIterator所要掃描的書架,而index字段則是指向目前該書的下標。
                構造函數把傳過來的BookShelf對象實例儲存在bookShelf字段,將index設置為0.
                實現的hasNext方法判斷是否有下一本書的標準是根據index是否小于書架上書籍的數量(表達式bookShelf.getLength()的值)來判斷。
                next方法返回目前該書,并進入到“下一個”。兩步:第一步先把取得當面的書籍保留在book變量,然后把循環變量推到“下一個”。


           1 package Iterator;
           2 
           3 public class Main {
           4     /**
           5      * @param args
           6      */
           7     public static void main(String[] args) {
           8         BookShelf bookShelf = new BookShelf(3);
           9         bookShelf.appendBook(new Book("book1"));
          10         bookShelf.appendBook(new Book("book2"));
          11         bookShelf.appendBook(new Book("book3"));
          12         Iterator it  = bookShelf.iterator();
          13         while(it.hasNext()){
          14             Book book = (Book)it.next();
          15             System.out.println(" "+book.getName());
          16         }
          17     }
          18 
          19 }
          20 

          Main類:
               1.先放三本書上架
                2.通過調用書架的iterator方法得到迭代器,來進行循環遍歷
                3.循環遍歷書籍,取出書,打印出書的名字。


          示例程序的執行結果 book1
           book2
           book3

          回顧一下,在迭代器模式中幾個重要“角色”:
               迭代器: 定義了訪問和遍歷元素的接口 ,它定義了能否取得下一個元素信息的的hasNext方法和取得下一個元素的next方法
              具體的迭代器:實現了迭代器的接口,如本例的BookShelfIterator,掌握遍歷時的重要信息。
              聚合:定義了建立了Iterator的接口。如本例的:Aggregate接口,定義了Iterator方法
             具體聚合:實現了聚合的所定義的接口,如本例的BookShelf,它實現了Iterator方法。


                [拓展思考]
                 有人回想,干嘛搞這么麻煩,用一個for不就是可以遍歷數組或List碼?思考一下迭代器的結構。Iterator是把定義和實現分開

                  while(it.hasNext()){
                                     Book book = (Book)it.next();
                                  System.out.println(" "+book.getName());
                    }
                這里我只調用了Iterator接口的hasNext和next方法,并沒有調用BookShelf實現遍歷是需要的方法,如:getBookAt()。這里的while不會收到BookShelf的實現影響。
                假設這里我們不采用數組來管理BookShelf,而采取與Java.util.Vector來管理。無論BookShelf的如何修改,都Main測試程序里無需修改任何程序就可以運行,這就是設計模式的優勢。設計模式是為了提高類的服用率,如果把一個零件修改了,就不想要修改其他使用了改零件的部分。

           
          posted @ 2007-07-27 15:22 回歸 閱讀(1184) | 評論 (2)編輯 收藏

                現在大多數Java軟件工程師面試都會問到這個問題:什么是單例模式(Singleton),能否寫出單例模式的示例代碼?單例模式是Gof中23個模式中最簡單最容易入門的模式,學習它我們能更理性的感知模式的意義.

               [形成]

                Singleton Pattern 為什么會出現?在我們軟件開發和架構中,經常遇到這樣的情形:我們需要一個類只能且僅能產生一個實例..比如表示一臺計算機的類,表示系統設定的類或者是表示窗口的類,還有為了節約資源,只讓產生一個實例..
               
                如何構造這種情形?Singleton模式給我一個方案:


               [代碼示例]
                
                程序列表
             

          名稱

          說明

          Singleton

          只有一個對象實例的類

          Main

          測試用的類



                [UML圖]
             
                

          [示例代碼和類的詮釋]

           1 package singleton;
           2 
           3 public class Singleton {
           4     private static Singleton singleton = new Singleton();
           5 
           6     private Singleton() {
           7         System.out.println("Create instance...");
           8     }
           9 
          10     public static Singleton getInstance() {
          11         return singleton;
          12     }
          13 }
          14 


                    Singleton  Class:
                      
                      1.該類只能產生一個對象實例

                      2.把該類的的singleton屬性設定為static再以Singleton;類的對象實例進行初始化,這個初始化的過程僅加載Sington類的時候調用一次.(Line4) 

                      3.把Singleton 類的構造函數限定為private,目的是為了防止從非Singleton類(其他類)調用構造函數來產生實例,如果通過new方式來產生Singleton實例,會出現編譯錯誤.這樣做是為了保險己見.(Line6) 

                      4.要得到Singleton實例的唯一方法就是調用類靜態方法getInstance().這個名字可以隨便取,只要方便理解就行.(Line 10) 

           1 package singleton;
           2 
           3 public class Main {
           4 
           5     public static void main(String[] args) {
           6         System.out.println("Start");
           7         Singleton obj1 = Singleton.getInstance();
           8         Singleton obj2 = Singleton.getInstance();
           9         if(obj1 == obj2){
          10             System.out.println("obj1和obj2是同一個對象實例");
          11         }else{
          12             System.out.println("obj1和obj2不是同一個對象實例");
          13         }
          14         System.out.println("End");
          15     }
          16 }
          17 


                 Main Class
                  1.該類是測試程序.
                  2.程序通過getInstance()方式產生兩個obj1和obj2實例.(Line 7,Line 8)
                  3.通過ojb1= =ojb2表達式來確定兩個對象是否相同,判定是否產生了Singleton的第二個示例.(Line9-12)
           

          示例程序的執行結果
          Start
          Create instance...
          obj1和obj2是同一個對象實例
          End

                   執行結果含義:
                          1. 的確如此,obj1和obj2是Singleton類的同一個且唯一的對象實例. 
                          2.當程序執行后,第一次調用getInstance的時候會初始化Singleton類,同時也會初始化static字段,也同時產生產生了一個唯一對象實例.




                [拓展思考]
             
          如下的另一一個單例模式的程序有什么隱患?

           1 package singleton;
           2 
           3 public class Singleton2 {
           4     
           5     private static Singleton2 singleton = null;
           6     
           7     private Singleton2(){
           8         System.out.println("已產生對象實例");
           9     }
          10     public static Singleton2 getInstance(){
          11         if(singleton == null){
          12             singleton = new Singleton2();
          13         }
          14         return singleton;
          15     }
          16 
          17 }
          18 

              [解答]
          當多線程同時調用Singleton2.getInstance()方法時,可能會產生多個對象實例,例如
          public class Main extends Thread{

              
          public static void main(String[] args) {
                  System.out.println(
          "Starts.");
                  
          new Main("A").start();
                  
          new Main("B").start();
                  
          new Main("C").start();
                  System.out.println(
          "End.");
              }

             
              
          public void run(){
                  Singleton2 obj 
          = Singleton2.getInstance();
                  System.out.println(getName()
          +": obj ="+obj);
              }

              
              
          public Main(String name){
                  
          super(name);
              }

          }




          public class Singleton2 {
              
          private static Singleton2 singleton2 = null;
              
          private Singleton2(){
                  System.out.println(
          "已產生對象實例");
                  solwDown();
              }


              
          public static Singleton2 getInstance(){
                  
          if(singleton2 == null){
                      singleton2 
          = new Singleton2();
                  }

                  
          return singleton2;
              }

              
               
          private  void solwDown(){
                   
          try{
                       Thread.sleep(
          1000);
                   }
          catch(InterruptedException e){
                       e.printStackTrace();
                   }

               }

          }


          執行結果:

          Start.
          End.
          已產生對象實例.
          已產生對象實例.
          已產生對象實例.
          B: obj = Singleton2#2a9348
          C: obj = Singleton2#b91134
          A: obj = Singleton2#e343l12

          (#替換為@)

          之所以會知道這種情況是因為if(singleton = = null){ singleton = new Singleton2(); }判斷不夠嚴謹的導致。
          利用: singleton == null 判斷為空后去執行new Singleton2()之前,可能會有其他線程來搶先判斷表達式singleton == null,從而又執行一遍創建實例的操作。

          解決辦法:
          給getInstance()方法添加Synchronized修飾符,即可修改成線程安全嚴謹的單例模式。

          public class Singleton2 {
              
          private static Singleton2 singleton = null;

              
          private Singleton2() {
                  System.out.println(
          "已產生對象實例");
                  solwDown();
              }

              
          public static synchronized Singleton2 getInstance() {
                  
          if (singleton == null) {
                      singleton 
          = new Singleton2();
                  }
                  
          return singleton;
              }

              
          private void solwDown() {
                  
          try {
                      Thread.sleep(
          1000);
                  } 
          catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              }
          }

          posted @ 2007-06-08 11:36 回歸 閱讀(1221) | 評論 (7)編輯 收藏

                [UML漫談]
                話說"工欲善其工需利其器",有了好的工具,好的表達方式,能給我們的工作變得簡單而優雅.

                為了更好的講解設計模式,方便理解,需要運用一種建模設計語言----UML.

                 UML(UML:Unified Modeling Language),即統一建模語言,用來對軟件密集系統進行描述、構造、視化和文檔編制的一種語言.這是概念,不好理解.

                 UML的作用,打個比方:一段描寫迷人海灘風景的文字和一幅描繪海灘風景的油畫,去看這兩件東西的人,有的人可能能讀懂文字(可能是特定的語言),有的不認字,所以并不是所有的人能看懂文字表達的內容,但是所有的人都能讀懂油畫所表現出來的含義.油畫表達內容的直接,形象,豐富特性就類型UML在描敘軟件結構過程中的作用.

                 在軟件項目中,一般有幾個角色:用戶(User),架構設計師(orPM, SA),程序員(PG)

                   用戶:
                         也許不懂計算機,也不懂編程語言,但是懂行業業務,該軟件的功能需求.

                 程序員
                        懂計算技術,懂編程語言.但是不太了解行業邏輯.需要把客戶的業務應用需求轉變為程序代碼,
                   
                 架構設計師
                         資深的行業架構設計師應該具有一定的行業知識,既能聽懂客戶的業務需求,又能知道怎么告訴程序員去用代碼實現.

                   架構設計師在前兩者交流中起到承前啟后的"中間體"作用.UML就是采用圖形化的形式來表達架構和設計.成為了建模設計的通用的設計標準..


          UML圖讓信息交流變得簡單

                
               [UML基礎]
                

             此處只介紹幫助理解設計模式的UML基礎,具體其他的UML圖示需要參考具體的講解UML的書籍.
              1.類的層級關系
                    UML中的類圖是一種可表示一組類,對象實例和接口之間的靜態關系圖.




          如圖的UML類圖表達了上面代碼的含義,

          類之間的關系有四種:依賴,泛化,實現聚集,組成.具體的UML實例可以參UML基礎.

          2.接口和實現

                實現接口的UML示例如下:


          interface Printable {
              
          abstract void print();
          }
          public class PrintClass implements Printable {

              
          public void print() {
                  
          // how to print
              }

          }

          接口,抽象,實現,繼承在設計模式中被廣泛的使用,這也是OOD的優勢所在.美妙所在.

          這里只舉出了幾個簡單情形,讓大家有個感性的了解,具體的情形在說具體的設計模式的時候在針對性的說明,先不用弄那么多,那么雜,能開始下一步就足夠.

          類之間的關系

          類之間的關系有5種,關聯 依賴 聚集 泛化 實現
          posted @ 2007-06-08 09:53 回歸 閱讀(1067) | 評論 (0)編輯 收藏

          主站蜘蛛池模板: 绥滨县| 腾冲县| 岢岚县| 南澳县| 洮南市| 太仆寺旗| 科技| 凉城县| 宝清县| 沧源| 固原市| 扶余县| 青河县| 彝良县| 万安县| 长汀县| 承德市| 德保县| 勃利县| 沙湾县| 新闻| 惠东县| 嘉义市| 焦作市| 汉沽区| 友谊县| 黑龙江省| 汶川县| 南充市| 华池县| 乌兰县| 山西省| 诸暨市| 长汀县| 龙岩市| 齐齐哈尔市| 姜堰市| 浙江省| 托克逊县| 三亚市| 沙坪坝区|