迭代器模式

定义

迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示

设计原则;
单一责任: 一个类应该只有一个引起变化的原因

内聚: 用来度量一个类或模块紧密的达到单一目的或责任; 当一个模块或一个类被设计成只支持一组相关的功能时, 我们说他具有高内聚

好处:**

  • 使用迭代器有了一个统一的方法去访问聚合中的元素, 因此可以使用多态
  • 迭代器模式把在元素之间游走的责任交给了迭代器, 而不是聚合对象, 不仅让聚合的接口和实现变得更简洁, 也可以让聚合更专注于他所应该专注的事情上面

案例

背景: 餐厅和煎饼屋合并, 煎饼屋提供早餐, 餐厅提供午餐, 其中煎饼屋菜单用ArrayList集合装菜单项, 餐厅菜单用数组来装菜单项, 侍女只需要一份菜单, 列出所有的菜单项, 如何设计系统
原始设计:
image.png
Waitress代码:

  1. public class Waitress {
  2. public void printMenu() {
  3. PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
  4. List<MenuItem> menuItemList = pancakeHouseMenu.getMenuItems();
  5. for (MenuItem menuItem : menuItemList) {
  6. System.out.println(menuItem);
  7. }
  8. DinerMenu dinerMenu = new DinerMenu();
  9. MenuItem[] menuItemsArray = dinerMenu.getMenuItems();
  10. for (MenuItem menuItem : menuItemsArray) {
  11. System.out.println(menuItem);
  12. }
  13. }
  14. }

使用迭代器模式并优化结构后:
image.png
由于数组没有实现迭代器接口, 需要自定义迭代器

  1. public class DinerMenuIterator implements Iterator {
  2. private MenuItem[] menuItems;
  3. int positon = 0;
  4. public DinerMenuIterator(MenuItem[] menuItems) {
  5. this.menuItems = menuItems;
  6. }
  7. @Override
  8. public boolean hasNext() {
  9. if (positon >= menuItems.length || menuItems[positon] == null) {
  10. return false;
  11. } else {
  12. return true;
  13. }
  14. }
  15. @Override
  16. public Object next() {
  17. return menuItems[positon++];
  18. }
  19. public MenuItem[] getMenuItems() {
  20. return menuItems;
  21. }
  22. public void setMenuItems(MenuItem[] menuItems) {
  23. this.menuItems = menuItems;
  24. }
  25. }

Waitress代码优化

  1. public class Waitress {
  2. private Menu pancakeHouseMenu;
  3. private Menu dinerMenu;
  4. public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
  5. this.pancakeHouseMenu = pancakeHouseMenu;
  6. this.dinerMenu = dinerMenu;
  7. }
  8. public void printMenu() {
  9. printMenu(pancakeHouseMenu.createIterator());
  10. printMenu(dinerMenu.createIterator());
  11. }
  12. private void printMenu(Iterator iterator) {
  13. while (iterator.hasNext()) {
  14. System.out.println(iterator.next());
  15. }
  16. }
  17. }

测试:

  1. @Test
  2. public void testIterator() {
  3. Waitress waitress = new Waitress(new PancakeHouseMenu(), new DinerMenu());
  4. waitress.printMenu();
  5. }
  6. 测试结果:
  7. MenuItem{name='煎饼1'}
  8. MenuItem{name='煎饼2'}
  9. MenuItem{name='煎饼3'}
  10. MenuItem{name='煎饼4'}
  11. MenuItem{name='肉'}
  12. MenuItem{name='蛋'}
  13. MenuItem{name='菜'}


使用迭代器模式优化后:
1.菜单的实现被封装, 侍女无需知道菜单如何存储菜单项
2.将两个循环的代码抽取了出来, 调用迭代器的方法
3.侍女依赖于Menu接口, 可以使用多态, 减少了对具体类的依赖

组合模式

定义

组合模式允许你将对象组合成树形结构来表现”整体/部分”层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合
**

案例

image.png