Head First 设计模式 —— 10. 迭代器 (Iterator) 模式

思考题

public void printMenu() {
    PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    ArrayList breakfastItems = pancakeHouseMenu.getMenuItems();
    
    DinerMenu dinerMenu = new DinerMenu();
    MenuItem[] lunchItems = dinerMenu.getMenuItems();
    
    for (int i = 0; i < breakfastItems.size(); ++i) {
        MenuItem menuItem = (MenuItem) breakfastItems.get(i);
        System.out.print(menuItem.getName() + " ");
        System.out.println(menuItem.getPrice() + " ");
        System.out.println(menuItem.getDescription());
    }
    
    for (int i = 0; i < lunchItems.length; ++i) {
        MenuItem menuItem = lunchItems[i];
        System.out.print(menuItem.getName() + " ");
        System.out.println(menuItem.getPrice() + " ");
        System.out.println(menuItem.getDescription());
    }
}

根据咱们的 printMenu() 实现,下列哪一项为真? P322java

  • [x] A. 咱们是针对 PancakeHouseMenuDinerMenu 的具体实现编码,而不是针对接口。git

    • 针对具体实现编程,没有解耦,没法动态替换
  • [ ] B. 女招待没有实现 Java 招待 API ,因此她没有遵照标准。github

    • 女招待有一个招待规格,算是实现了一个隐式 API,而且内部实现封装了变化
  • [x] C. 若是咱们决定从 DinerMenu 切换到另外一种菜单,此菜单的项是用 Hashtable 来存放的,咱们会所以须要修改女招待中的许多代码。编程

    • Hashtable 是一种新的具体实现,须要修改代码进行适配
  • [x] D. 女招待须要知道每一个菜单如何表达内部的菜单项集合,这违反了封装。segmentfault

    • 女招待的实现依赖菜单内部实现,与菜单强耦合,没有封装变化
  • [x] E. 咱们有重复的代码; printMenu() 方法须要两个循环,来遍历两种不一样的菜单。若是咱们加上第三种菜单,咱们就须要第三个循环。框架

    • 因为是针对菜单项集合的具体实现编程,因此增长新菜单就须要增长循环
  • [ ] F. 这个实现并无基于 MXML(Menu XML),因此就没有办法互操做。ide

    • The implementation isn't based on MXML(Menu XML) and so isn't as interoperable as it shoule be.
    • 互操做性(英文:Interoperability;中文又称为:协同工做能力,互用性)做为一种特性,它指的是不一样的系统和组织机构之间相互合做,协同工做(即互操做)的能力。就软件而言,互操做性——这条术语用来描述的是不一样的程序(programs)借助于同一套交换格式(exchange formats)来交换数据,读写相同文件格式(file formats)以及采用相同协议(protocols)的能力。
    • 刚开始不懂,看了维基百科后的解释后有点似懂非懂。这个实现内部直接处理了不一样数据格式,具备必定的互操做性。

思考题

请继续完成 PancakeHouseIterator 的实现,并对 PancakeHouseMenu 类作出必要的修改。 P327this

public class PancakeHouseIterator implements Iterator {
    ArrayList items;
    int position = 0;
    
    public PancakeHouseIterator(ArrayList items) {
        this.items = items;
    }
    
    public Object next() {
        return items.get(position++);
    }
    
    public boolean hasNext() {
        return position >= items.size();
    }
}

public class PancakeHouseMenu {
    ArrayList menuItems;
    
    // 构造器和其余方法
    // 移除 public ArrayList getMenuItems() 方法
    
    public Iterator createIterator() {
        return new PancakeHouseIterator(menuItems);
    }
}

迭代器模式

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

特色
  • 遍历集合内部元素而不暴露内部表示 P336
  • 让聚合的接口和实现变得简洁 P336
  • 管理对象集合,没必要理会遍历的事情 P336

思考题

迭代器模式的类图看起来很像咱们所学过的另外一个模式;你知道是哪一个模式吗?提示:子类决定要建立哪一个对象。 P337idea

  • 工厂方法模式

设计原则

单一职责原则:一个类应该只有一个引发变化的缘由 P339

  • 高内聚:一个模块或一个类只支持一组相关的功能 P339
特色
  • 尽可能将一个责任只指派给一个类 P339
  • 遵循单一职责原则的类是高内聚的 P339

思考题

请很快写下为了能让咖啡厅的菜单代码符合咱们的框架,咱们要对它作的三件事情: P342

public class CafeMenu {
    HashTable menuItems = new Hashtable(); 
    
    public CafeMenu() {
        // 省略下述参数
        // addItem(...);
        // addItem(...);
        // addItem(...);
    }
    
    public void addItem(String name, String description, boolean vegetarian, double price) {
        MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
        menuItems.put(menuItem.getName(), menuItem);
    }
    
    public Hashtable getItems() {
        return menuItems;
    }
}
  • 实现 Menu 接口
  • 删除 getItems() 方法
  • 增长 createIterator() 方法
本文首发于公众号:满赋诸机( 点击查看原文) 开源在 GitHub : reading-notes/head-first-design-patterns
相关文章
相关标签/搜索