Head First 设计模式 --9 迭代器模式 组合模式

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

 用到的设计原则:
1、封装变化
2、多用组合,少用继承|
3、针对接口编程,不针对实现编程
4、松耦合
5、对扩展开放,对修改关闭
6、依赖抽象,不依赖具体
7、只和朋友交谈
8、别找我,我会找你
9、类应该只有一个改变的理由

迭代器模式非常简单,直接看代码(代码的意思,PancakeHouseMenu和DinerMenu两种菜单,一个用了list一个用了数组,分别对应两种类型的Iterator方便Waitress操作菜单)

class Waitress {
  Menu pancakeHouseMenu;
  Menu dinerMenu;

  public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
    this.pancakeHouseMenu = pancakeHouseMenu;
    this.dinerMenu = dinerMenu;
  }

  public void printMenu() {
    Iterator<MenuItem> pancakeIterator = pancakeHouseMenu.createIterator();
    Iterator<MenuItem> dinerIterator = dinerMenu.createIterator();
    printMenu(pancakeIterator);
    printMenu(dinerIterator);
  }

  private void printMenu(Iterator<MenuItem> iterator) {
    while (iterator.hasNext()) {
      MenuItem menuItem = (MenuItem) iterator.next();
      System.out.println(menuItem.getName());
      System.out.println(menuItem.getPrice());
    }
  }
}

class MenuItem {
  String name;
  double price;

  public MenuItem(String name, double price) {
    this.name = name;
    this.price = price;
  }

  public String getName() {
    return name;
  }

  public double getPrice() {
    return price;
  }
}

interface Menu {
  public Iterator<MenuItem> createIterator();
}


class DinerMenuIterator implements Iterator<MenuItem> {
  MenuItem[] items;
  int position;

  public DinerMenuIterator(MenuItem[] items) {
    this.items = items;
  }

  @Override
  public boolean hasNext() {
    if (position >= items.length || items[position] == null) {
      return false;
    } else {
      return true;
    }
  }

  @Override
  public MenuItem next() {
    MenuItem menuItem = items[position];
    position = position + 1;
    return menuItem;
  }

  public void remove() {
    if (position <= 0) {
      throw new IllegalStateException();
    }
    if (items[position - 1] != null) {
      for (int i = position - 1; i < (items.length - 1); i++) {
        items[i] = items[i + 1];
      }
      items[items.length - 1] = null;
    }
  }


}

class DinerMenu implements Menu {
  static final int MAX_ITEMS = 6;
  int numberOfItems = 0;
  MenuItem[] menuItems;

  public DinerMenu() {
    menuItems = new MenuItem[MAX_ITEMS];
    addItem("diner breakfase", 1.00);

  }

  public void addItem(String name, double price) {
    MenuItem menuItem = new MenuItem(name, price);
    if (numberOfItems >= MAX_ITEMS) {
      System.out.println("menu is full");
    } else {
      menuItems[numberOfItems] = menuItem;
      numberOfItems = numberOfItems + 1;
    }
  }

  public Iterator<MenuItem> createIterator() {
    return new DinerMenuIterator(menuItems);
  }
}

class PancakeHouseIterator implements Iterator<MenuItem> {
  ArrayList<MenuItem> items;
  int position;

  public PancakeHouseIterator(ArrayList<MenuItem> items) {
    this.items = items;
  }

  @Override
  public boolean hasNext() {
    if (position >= items.size() || items.get(position) == null) {
      return false;
    } else {
      return true;
    }
  }

  @Override
  public MenuItem next() {
    MenuItem menuItem = items.get(position);
    position = position + 1;
    return menuItem;
  }

  public void remove() {
    if (position <= 0) {
      throw new IllegalStateException();
    }
    items.remove(position);
  }

}

class PancakeHouseMenu implements Menu {
  ArrayList<MenuItem> menuItems;

  public PancakeHouseMenu() {
    menuItems = new ArrayList<>();
    addItem("pancake house breakfase", 1.00);

  }

  public void addItem(String name, double price) {
    MenuItem menuItem = new MenuItem(name, price);
    menuItems.add(menuItem);
  }

  public Iterator<MenuItem> createIterator() {
    return new PancakeHouseIterator(menuItems);
  }
}

public class Test {
  public static void main(String[] args) {
    PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    DinerMenu dinerMenu = new DinerMenu();

    Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
    waitress.printMenu();
  }
}

类图:

虽然代码有点多,但是还是很好理解。代码多只是因为为了用一个真实点的例子,类多了点。

 迭代器模式的类图:

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

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

组合模式可以理解为迭代器的扩展,如果菜单中还有子菜单,那么迭代器模式就无法解决了。这是就可以考虑用组合模式。

class TreeNode {

  private String name;
  private TreeNode parent;
  private Vector<TreeNode> children = new Vector<TreeNode>();

  public TreeNode(String name) {
    this.name = name;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public TreeNode getParent() {
    return parent;
  }

  public void setParent(TreeNode parent) {
    this.parent = parent;
  }

  // 添加孩子节点
  public void add(TreeNode node) {
    children.add(node);
  }

  // 删除孩子节点
  public void remove(TreeNode node) {
    children.remove(node);
  }

  // 取得孩子节点
  public Enumeration<TreeNode> getChildren() {
    return children.elements();
  }
}


class Tree {

  TreeNode root = null;

  public Tree(String name) {
    root = new TreeNode(name);
  }
}

public class CompositeTest {
  public static void main(String[] args) {
    Tree tree = new Tree("A");
    TreeNode nodeB = new TreeNode("B");
    TreeNode nodeC = new TreeNode("C");
    TreeNode nodeD = new TreeNode("D");

    nodeB.add(nodeC);
    nodeB.add(nodeD);
    tree.root.add(nodeB);
    tree.root.getChildren();
  }
}

这个模式没用书里的例子( http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html ),组合模式主要是用在树形结构中。

一般情况下,组合模式和迭代器模式搭配使用(获取所有子节点的地方)。

原文地址:https://www.cnblogs.com/badboyf/p/6222820.html