9.迭代器與組合模式
Head-First-Design-Patterns-master\src\headfirst\designpatterns\iterator
Head-First-Design-Patterns-master\src\headfirst\designpatterns\composite
迭代器模式定義:提供一種方法順序訪問一個集合物件中的各個元素,而又不暴漏其內部的表示
案例:
物件村餐廳和物件村煎餅屋合併了
物件村餐廳選單用的是ArrayList儲存清單
物件村煎餅屋選單用的是資料儲存清單
實現一個java版的服務員。
例如實現取出清單,兩種方法
ArrayList menu 使用menu.get(i)
MenuItem[] menu 使用 menu[i]
使用迭代器方式相容
ArrayList和陣列都使用
Iterator it=menu.createIterator();
hasNext()和next()方法
public class DinerMenu implements Menu { static final int MAX_ITEMS = 6; int numberOfItems = 0; MenuItem[] menuItems; public DinerMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99); addItem("BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99); addItem("Soup of the day", "Soup of the day, with a side of potato salad", false, 3.29); addItem("Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05); addItem("Steamed Veggies and Brown Rice", "Steamed vegetables over brown rice", true, 3.99); addItem("Pasta", "Spaghetti with Marinara Sauce, and a slice of sourdough bread", true, 3.89); } public void addItem(String name, String description, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, description, vegetarian, price); if (numberOfItems >= MAX_ITEMS) { System.err.println("Sorry, menu is full! Can't add item to menu"); } else { menuItems[numberOfItems] = menuItem; numberOfItems = numberOfItems + 1; } } public MenuItem[] getMenuItems() { return menuItems; } public Iterator<MenuItem> createIterator() { return new DinerMenuIterator(menuItems); //return new AlternatingDinerMenuIterator(menuItems); } // other menu methods here } public class DinerMenuIterator implements Iterator<MenuItem> { MenuItem[] list; int position = 0; public DinerMenuIterator(MenuItem[] list) { this.list = list; } public MenuItem next() { MenuItem menuItem = list[position]; position = position + 1; return menuItem; } public boolean hasNext() { if (position >= list.length || list[position] == null) { return false; } else { return true; } } public void remove() { if (position <= 0) { throw new IllegalStateException ("You can't remove an item until you've done at least one next()"); } if (list[position-1] != null) { for (int i = position-1; i < (list.length-1); i++) { list[i] = list[i+1]; } list[list.length-1] = null; } } } public class Waitress { Menu pancakeHouseMenu; Menu dinerMenu; public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) { this.pancakeHouseMenu = pancakeHouseMenu; this.dinerMenu = dinerMenu; } public void printMenu() { Iterator pancakeIterator = pancakeHouseMenu.createIterator(); Iterator dinerIterator = dinerMenu.createIterator(); System.out.println("MENU\n----\nBREAKFAST"); printMenu(pancakeIterator); System.out.println("\nLUNCH"); printMenu(dinerIterator); } private void printMenu(Iterator iterator) { while (iterator.hasNext()) { MenuItem menuItem = iterator.next(); System.out.print(menuItem.getName() + ", "); System.out.print(menuItem.getPrice() + " -- "); System.out.println(menuItem.getDescription()); } } public void printVegetarianMenu() { printVegetarianMenu(pancakeHouseMenu.createIterator()); printVegetarianMenu(dinerMenu.createIterator()); } public boolean isItemVegetarian(String name) { Iterator breakfastIterator = pancakeHouseMenu.createIterator(); if (isVegetarian(name, breakfastIterator)) { return true; } Iterator dinnerIterator = dinerMenu.createIterator(); if (isVegetarian(name, dinnerIterator)) { return true; } return false; } private void printVegetarianMenu(Iterator iterator) { while (iterator.hasNext()) { MenuItem menuItem = iterator.next(); if (menuItem.isVegetarian()) { System.out.print(menuItem.getName()); System.out.println("\t\t" + menuItem.getPrice()); System.out.println("\t" + menuItem.getDescription()); } } } private boolean isVegetarian(String name, Iterator iterator) { while (iterator.hasNext()) { MenuItem menuItem = iterator.next(); if (menuItem.getName().equals(name)) { if (menuItem.isVegetarian()) { return true; } } } return false; } } public interface Menu { public Iterator<?> createIterator(); }
單一責任:
一個類應該只有一個引起變化的原因
當一個模組或一個類被設計成只支援一組相關的功能時,我們說它具有高內聚。
內聚是比單一責任原則更普遍的概念。
Hashtable也支援迭代器,只不過是對雜湊值的集合的迭代器。
Collection和Iterator的好處在於,每個Collection都知道如何建立自己的Iterator。只要呼叫ArrayList上的Iterator90就可以返回一個具體的Iterator,而你根本不需要知道或者關心到底使用了哪個具體類,你只要使用它的Iterator介面就可以了。
java 5對所有集合的迭代器
for(Object obj: collection){}
當遇到擴充套件子選單的時候,程式碼需要重構了
能夠用樹形來表示選單
定義組合模式:
允許你將物件組合成樹形結構來表示“整體/部分”層次結構,組合能夠讓客戶以一致的方式處理個別對象以及物件組合。
元件、組合、樹的關係:
組合包含元件。元件有兩種:組合與葉節點元素。聽起來像遞迴,組合持有一群孩子,這些孩子可以是別的組合或者葉節點元素。使用這種方式組織資料時,最終會得到樹形結構
使用組合設計選單
建立元件介面
public abstract class MenuComponent {
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public double getPrice() {
throw new UnsupportedOperationException();
}
public boolean isVegetarian() {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
}
//屬於葉節點,具體實現一個菜品
public class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,
String description,
boolean vegetarian,
double price)
{
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public double getPrice() {
return price;
}
public boolean isVegetarian() {
return vegetarian;
}
public void print() {
System.out.print(" " + getName());
if (isVegetarian()) {
System.out.print("(v)");
}
System.out.println(", " + getPrice());
System.out.println(" -- " + getDescription());
}
}
//選單繼承選單元件是因為,子選單也是在選單中的一個擴充套件,相對葉節點(菜品)來說,選單具有對子選單的一些行為而不是具體實現一個菜品。
public class Menu extends MenuComponent {
ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
String name;
String description;
public Menu(String name, String description) {
this.name = name;
this.description = description;
}
public void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
public void remove(MenuComponent menuComponent) {
menuComponents.remove(menuComponent);
}
public MenuComponent getChild(int i) {
return (MenuComponent)menuComponents.get(i);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public void print() {
System.out.print("\n" + getName());
System.out.println(", " + getDescription());
System.out.println("---------------------");
Iterator<MenuComponent> iterator = menuComponents.iterator();
while (iterator.hasNext()) {
MenuComponent menuComponent =
(MenuComponent)iterator.next();
menuComponent.print();
}
}
}