Iterator Pattern
问题:
面对多个集合对象(不一定使用相同集合容器)时, 如何设置使其 遍历和操作统一化
public class AMenu { ArrayList menuItems; public AMenu() { menuItems = new ArrayList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public ArrayList getMenuItems() { return menuItems; } } |
public class BMenu { int index = 0; MenuItem[] menuItems; public BMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public MenuItem[] getMenuItems() { return menuItems; } } |
public class Waitree { AMenu aMenu = new AMenu(); BMenu bMenu = new BMenu(); void printMenu() { ArrayList AItems = aMenu.getMenuItems(); MenuItem[] BItems = bMenu.getMenuItems(); printMenu(AItems); printMenu(BItems); } void printMenu(ArrayList array) { foreach(var a in AItems) { MenuItem item = (MenuItem)AItems.get(i); } } void printMenu(MenuItem[] list) { foreach(var b in BItems) { MenuItem item = BItems[i]; // do something } } } |
这里可以看出 Waitree 对每个对象都使用了不同的遍历方式, 针对不同类型需要有不同类型的实现,
但就抽象意义来说, 都是遍历, 所以需要抽象
所以:
先针对不同的 集合类型设置不同的迭代器
public interface Iterator { bool hasNext(); object Next(); } |
|
public class AMenuIterator : Iterator { ArrayList items; public AMenuIterator(ArrayList){ this.items = items; } bool hasNext(){}; object Next(){}; } |
public class BMenuIterator : Iterator { MenuItem[] items; int index = 0; public BMenuIterator(MenuItem[] items){ this.items = items; } bool hasNext(){} object Next(){} } |
然后修改实现的类
public class AMenu { ArrayList menuItems; public AMenu() { menuItems = new ArrayList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new AMenuIterator(menuItems); } } |
public class BMenu { int index = 0; MenuItem[] menuItems; public BMenu() { menuItems = new MenuItem[MAX_ITEMS]; addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new BMenuIterator(menuItems); } } |
public class Waitree() { AMenu aMenu = new AMenu(); BMenu bMenu = new BMenu(); void printMenu() { Iterator AItems = aMenu.getMenuItems(); Iterator BItems = bMenu.getMenuItems(); printMenu(AItems); printMenu(BItems); } void printMenu(Iterator iterator) { while(iterator.hasNext()){ show(iterator.next()); } } } |
这样就可以吧不同类型的集合封装成一个抽象, 针对这个抽象操作达到对所有(几乎所有)的集合容器的操作
问题:
现在还是需要实例化两个不同的菜单类, 是否可以将不同的 Menu 抽象
所以:
public interface Menu { Iterator getMenuItems(); } |
public class Waitree() { Menu aMenu = new AMenu(); Menu bMenu = new BMenu(); void printMenu() { Iterator AItems = aMenu.getMenuItems(); Iterator BItems = bMenu.getMenuItems(); printMenu(AItems); printMenu(BItems); } void printMenu(Iterator iterator) { while(iterator.hasNext()){ show(iterator.next()); } } } |
问题:
现在需要再增加多个相同的 菜单, 如果不进行重构 在 Waitree 中会出现十分多的相同的类
public class CMenu : Menu { LinkList menuItems; public CMenu() { menuItems = new LinkList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new AMenuIterator(menuItems); } } |
public class DMenu : Menu { LinkList menuItems; public DMenu() { menuItems = new LinkList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new AMenuIterator(menuItems); } } |
public class EMenu : Menu { LinkList menuItems; public EMenu() { menuItems = new LinkList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new AMenuIterator(menuItems); } } |
public class FMenu : Menu { LinkList menuItems; public FMenu() { menuItems = new LinkList(); addItem("a"); addItem("b"); addItem("c"); // ...... } public void addItem(string s){} public Iterator getMenuItems() { return new AMenuIterator(menuItems); } } |
public class Waitree { Menu aMenu = new AMenu(); Menu bMenu = new BMenu(); Menu cMenu = new CMenu(); // ......... void printMenu() { Iterator AItems = aMenu.getMenuItems(); Iterator BItems = bMenu.getMenuItems(); Iterator CItems = cMenu.getMenuItems(); // ................... printMenu(AItems); printMenu(BItems); printMenu(CItems); // .................... } void printMenu(Iterator iterator) { while(iterator.hasNext()){ show(iterator.next()); } } } |
所以:
需要将重复的部分封装成一个集合
public class Waitree() { ArrayList menus; void printMenu() { Iterator menuIterator = menus.iterator(); while(menuIterator.hasNext()){ Menu menu = (Menu)menuIterator.next(); printMenu(menu.getMenuItems()); } } void printMenu(Iterator iterator) { while(iterator.hasNext()){ show(iterator.next()); } } }
问题:
这样一来, 可能在菜单中会存在子菜单.
所以:
将菜单的结构调整为树形结构....