設計模式之迭代器與組合模式(一)
- 2019 年 12 月 26 日
- 筆記
很高興,這本書總共13章,這次已經是到第9章了;同時也很遺憾,小編脫離了書本,還是不知道如何描述一個設計模式。就比如迭代器與組合模式,原書篇幅比較長,小編盡量通俗易懂些,不到之處,還請各位小夥伴參考原書,小編也歡迎和大家一起交流。
有許多種方法可以把對象堆起來成為一個集合(collection)。你可以把它們放進數組、堆棧、列表或是散列表中,這是你的自由。每一種都有它自己的優點和適合的使用時機,但如果你想要遍歷這些對象,怎麼辦呢?不用擔心,接下來的學習就是如何能讓客戶遍歷你的對象而又無法窺視你存儲對象的方式;也將學習如何創建一些對象超集合,能夠一口氣就跳過某些讓人望而生畏的數據結構。
對象村餐廳和對象村煎餅屋合併了
在面向對象的世界裡,小夥伴們都開心的不要不要的,因為現在他們可以在同一個地方,享受煎餅屋美味的煎餅早餐,和好吃的餐廳午餐了。但是,有一點小麻煩……
煎餅屋記錄的菜單項是使用數組來存儲的,而餐廳是使用ArrayList記錄他的菜單項,兩家店長都不願意改變現在的實現,畢竟有太多的程式碼依賴了,而我們又想減少依賴,用最小的改動。
兩種表現形式會帶來什麼問題
想了解為什麼有兩種不同的菜單表現方式會讓事情變得複雜化,讓我們試著實現一個同時使用這兩個菜單的客戶程式碼。
我們新聘請了一位服務員,能應對顧客的需要列印訂製的菜單,甚至告訴你是否某個菜單項是素食的,而無需詢問廚師。要求如下:
- printMenu():列印出菜單上的每一項
- printBreakfastMenu():值列印早餐項
- printLunchMenu():只列印午餐項
- printVegetarianMenu():列印所有的素食菜單項
- isItemVegetarian(name):指定項的名稱,如果該項是素食的話,返回true,否則返回false
實現上來說,如下所示:
- 列印每份菜單上的所有項,必須調用PancakeHouseMenu和DinerMenu的getMenuItem()方法,來取得它們各自的帶單項
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); ArrayList breakfastItems = pancakeHouseMenu.getMenuItems(); DinerMenu dinerMenu = new DinerMenu(); MenuItem[] lunchItems = dinerMenu.getMenuItems();
- 現在,分別列印裡面的具體項目,早餐使用ArrayList,午餐使用數組
for (int i = 0; i < breakfastItems.size(); i++) { MenuItem menuItem = (MenuItem)breakfastItems.get(i); System.out.print(menuItem.getName()); System.out.println("tt" + menuItem.getPrice()); System.out.println("t" + menuItem.getDescription()); } for (int i = 0; i < lunchItems.length; i++) { MenuItem menuItem = lunchItems[i]; System.out.print(menuItem.getName()); System.out.println("tt" + menuItem.getPrice()); System.out.println("t" + menuItem.getDescription()); }
- 實現其他方法,做法也都和這一頁的方法相類似。我們總是需要處理兩個菜單,並且用兩個循環遍歷這些項。如果還有第三家餐廳以不同的實現出現,我們就需要有三個循環。
下一步怎麼辦?
他們都不想改變自身的實現,因為意味著要重寫許多程式碼。所以,如果我們能夠找出一個方法,讓他們的菜單實現一個相同的介面,這該多好呢。我們試試看封裝。
這本書給我們最大的改變,就是封裝變化的部分。在這裡發生的變化是:由不同的集合類型所造成的遍歷。能被封裝嗎?我們繼續來分析下:
- 要遍歷早餐項,我們需要使用ArrayList的size()和get()方法
for(int i = 0; i < breakfastItems.size(); i++) { MenuItem menuItem = (MenuItem)breakfastItems.get(i); }
- 要遍歷午餐項,我們需要使用數組的length欄位和中括弧
for (int i = 0; i < lunchItems.length; i++) { MenuItem menuItem = lunchItems[i]; }
- 現在我們創建一個對象,我們把它稱為迭代器(Iterator),利用它來封裝「遍歷集合內的每個對象的過程」
Iterator iterator = breakfastMenu.createIterator(); while (iterator.hasNext()) { MenuItem menuItem = (MenuItem) iterator.next(); }
- 將它在數組上試試:
Iterator iterator = lunchMenu.createIterator(); while (iterator.hasNext()) { MenuItem menuItem = (MenuItem) iterator.next(); }
看到這裡,可以看到,我們對遍歷的封裝已經奏效了;你大概已經猜到,這正是一個設計模式,稱為迭代器模式。那我們放在下次來具體說說,等著噢。
愛生活,愛學習,愛感悟,愛挨踢