设计模式之_Iterator_03
生活随笔
收集整理的這篇文章主要介紹了
设计模式之_Iterator_03
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 考慮容器的可替換性package com.learn.dp.iterator;/*** Collection叫集合,是一個統一的集合,所有的實現類都要實現這個接口* 有了接口之后呢,我們就用接口的方式統一了,凡是實現了我這個接口的子類,* 肯定有add和size方法,* @author Leon.Sun**/
public interface Collection {/*** 我就不寫public了,因為interface里面的方法都是public*/void add(Object o);int size();
}
package com.learn.dp.iterator;/*** 我們讓ArrayList來實現Collection接口* @author Leon.Sun**/
public class ArrayList implements Collection {/*** 我在這里定義一個數組,模擬可以裝任意多個對象的容器* 我們現在 一個數組往里頭裝任何的對象,加入這個數組里面能裝10個,* 一旦裝滿了之后,我就在這個數組的基礎上擴展一些新的空間,一旦裝滿了就再擴展新的空間* 這個時候我就可以往里頭裝任意多個對象了,所以這個寫法就簡單了,*/Object[] objects = new Object[10];/*** 默認情況下一個都沒裝,index代表下一個空位置在哪里* 最開始一個都沒有裝,當你裝的時候就在index這個位置上* 每當我們添加一個新的進來的時候,讓index++*/int index = 0;/*** 父類引用指向子類對象* 第一個容器我用數組來模擬,往里裝的時候要判斷一下,現在裝到哪了,* */public void add(Object o) {/*** 一旦你加到index==objects.length的時候,* 再往里面添加新對象的時候,超過他的容量了,這個時候把原來的數組做擴展*/if(index==objects.length) {/*** 當一個數組的容量不夠使了,我就new個新數組,新數組的容量是老數組的兩倍* 我們這么寫嚴格來講不是很科學,兩倍兩倍一直乘下去話數量級會非常大,根據原來有多長再加多少,* 不過我們的重點并不是放在這個地方,所以我采取最簡單的方式,把原來的數組copy到新數組里面,* */Object[] newObjects = new Object[objects.length * 2];/*** 這里用到了System類的靜態方法* 這個方法要是不理解去讀API文檔,其實每次用到arraycopy文檔的時候總想罵SUN兩句* 如果按照JAVA里面的變量駝峰標識風格的話,C一般大寫才對,可是這個C就是小寫* String類中的有一個substring第二個應該是大寫,結果他還是小寫,個人柑橘非常的別扭* SUN有時候這些細節上不是非常的到位,很慶幸的是JAVA已經被收購了,已經不控制在SUN手里了* 這個世界感覺美好了很多* 第一個參數objects原來的數組* 第二個參數從哪里開始* 第三個參數拷貝到哪個數組去* 第四個參數目標參數從哪里開始* 第五個參數是一共拷貝多少個* 原來數組滿了,所以一共拷貝這么多個*/System.arraycopy(objects, 0, newObjects, 0, objects.length);/*** 所以原來的引用就指向了新的數組*/objects = newObjects;}objects[index] = o;/*** 這樣index就記錄了我裝了多少個對象了* 每當我添加一個新對象,index都要往上加*/index++;}/*** 作為一個容器別人一般會問你裝了多少個東西了* 調用它的時候告訴容器裝了多少個了*/public int size() {/*** 裝了index個了*/return index;}}
package com.learn.dp.iterator;/*** LinkedList也讓他去實現Collection* @author Leon.Sun**/
public class LinkedList implements Collection {Node head = null;/*** 所以你會發現這樣一個問題,當我們添加新節點的時候,如果我們知道哪個節點是最后一個,* 那就爽很多了,因為我們只要讓最后一個拉住我們的小手就可以* 所以我們可以這么寫*/Node tail = null;/*** 要有一個東西記錄到底有多少個元素了* 其實這個size是冗余數據,你不記錄也可以* 但是我們有一個冗余數據,沒添加一個就讓他加加* 最后只要return size就可以了*/int size = 0;/*** 當我們往鏈表里添加一個節點的時候,這個時候我們該怎么做,* 當然你要做各種判斷,第一個如果head本身就是空的話,那么作為你新添加進來的內容,* 它就是第一個節點,添加進來新的Object* * 加入我們已經有了一個節點了,next指向一個空值,當我們再往里面添加一個節點的時候,* 把新的節點放在右邊,把前面的next指向它,如果還有第三個,新加進來的就指向空值* * @param o*/public void add(Object o) {/*** 真正的內容是傳進來的o,它的next是沒有,所以只能傳一個空值*/Node n = new Node(o,null);/*** 如果添加進來的是第一個節點,那head就等于n* head等于空,head等于n,tail也等于n* 你是第一個的話你既是頭也是尾,如果tail不等于空,那就是一回事*/if(head==null) {head = n;tail = n;}/*** 把tail的這只小手*/tail.setNext(n);/*** tail要變成本身加入進來的節點* 這樣一個新的節點就加入進來了*/tail = n;size++;}public int size() {return size;}}
package com.learn.dp.iterator;public class MainTest {public static void main(String[] args) {/*** 該用LinkedList* 我ArrayList用膩了,我就馬上改成LinkedList,其他的代碼不用變* 我現在并沒有任何一種機制來約束說這個方法就叫add,加入LinkedList里面的* 方法不叫add,叫addObject,那大家想一下,你從ArrayList換成LinkedList的時候* 那下面的話一定會發生改變,所以我們有必要定義這樣一種機制來把他們兩個公開的一些方法給他統一起來* 那我想大多人人能夠想到他的解決方案* * 我在定義定義具體容器的時候,*/// LinkedList ll = new LinkedList();/*** 一旦我不滿意了,我就換成LinkedList,放心下面一定都不會變* 原因是因為我通過c來調的,通過c來調只能看到Collection的接口* 只能看到add和size方法,反正你是具體的子類,一定會實現這兩個方法,* 下面我只是針對接口編程,針對接口編程就不用考慮我到底的具體實現類是什么,* 所以你會發現你的程序會更靈活,因為你要替換其他實現類的時候,只需要換一個地方* 如果你把這個東西放在配置文件里,你甚至連代碼都不用改,不知道剛剛講的有沒有明白,* 這就是他帶來的好處,面向接口編程,我們現在針對Collection接口編程,它具體的* 實現我不管他,代碼不用變,可以靈活的替代具體的實現,我們定義這個就更好了,* 不過新的問題馬上就要來了,我們考慮容器的可替換性,我想把這個容器的元素給遍歷出來,* 把他們都給我遍歷出來,你該怎么做,* */Collection c = new ArrayList();for(int i=0;i<15;i++) {c.add(new Cat(i));}System.out.println(c.size());}
}
?
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的设计模式之_Iterator_03的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式之_Iterator_02
- 下一篇: 设计模式之_Iterator_04