迭代器模式和组合模式-《Head First 设计模式》
来源:互联网 发布:手机apk反编译软件 编辑:程序博客网 时间:2024/05/21 10:52
问题汇总
- 迭代器定义和作用
迭代器遍历一个聚合物,并将其封装成另一个对象。 - 迭代器适用场景
- 迭代器模式的结构和实现方法
- 组合模式定义和作用以及适用场景
适用于“整体/部分”的关系结构,用于统一处理所有对象(不分节点还是叶子)。 - 组合模式结构和实现的两种方案。
- 树结构。
- 将所有功能都加入到Component中。或者将不同功能通过接口来赋予不同对象。其间的思想就是透明度和安全性的平衡。
- 迭代器设计原则:一个类一个功能。
- 观察者和状态模式的区别
- 观察者:当状态改变时,通知一组对象。
- 状态:当状态改变时,让一个对象改变行为。
问题答案日后补充
- 问题汇总
- 1-迭代器模式
- 1-定义
- 2-结构
- 使用
- 3-设计原则
- 4-Java5遍历集合而不用显式Iterator
- 5-实例餐厅
- 1-MenuItem
- 2-Menu
- 3-Iterator
- 4-服务员和测试
- 2-组合模式Composite Pattern
- 1-定义
- 2-结构
- 3-实例代码
- 1-Component
- 2-Composite
- 3-Leaf
- 4-对树根操作
- 5-测试
- 4-组合和迭代器结合
- 5-组合模式优点
1-迭代器模式
1-定义:
提供一种方法能够顺序访问聚合对象中的元素,而不需要暴露内部的表示。
2-结构:
- 聚合接口(Aggregate)-提供createIterator方法
- ConcreteAggregate-实现聚合接口中的createIterator方法
- Iterator(迭代器接口)-提供hasNext\next等方法
- ConcreteIterator(具体迭代器)-实现接口的方法
使用
通过ConcreteAggregate的createIterator()方法获得具体迭代器。使用具体迭代器中的hasNext()\next()遍历所有元素。
Iterator的古老版本是Enumeration,新旧版本之间的兼容可以用
Adapter Pattern
3-设计原则:
一个类应该只有一个引起变化的原因:一个责任只指派给一个类
高内聚:一个类只支持一组相关的功能。
- Hashtable是由两组数据组成:key和values。我们可以单独取出values调用其中的iterator()来获取迭代器。
4-Java5遍历集合而不用显式Iterator
for(Object obj : collection){...}
5-实例:餐厅
一个服务员有几个餐厅的菜单,各个餐厅的菜品组成方式都不相同。这里需要通过迭代器在不了解餐厅菜单内部细节的情况下,遍历所有的菜品。这里按照上面的结构,分为几个部分:菜品MenuItem,菜单接口Menu, 具体餐厅菜单DinerMenu等等,迭代器。
1-MenuItem
包含菜名和单价
public class MenuItem { String name; int price; public MenuItem(String name,int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } }
2-Menu
所有餐厅的菜单都实现Menu接口,并且实现了createIterator()
方法用于获取迭代器。
public interface Menu { public Iterator createIterator();}public class DinerMenu implements Menu{ MenuItem menuItems[] = new MenuItem[] {new MenuItem("diner1", 10) , new MenuItem("diner2", 14) , new MenuItem("diner3", 7)}; @Override public Iterator createIterator() { return new DinerMenuIterator(menuItems); }}public class PancakeHouseMenu implements Menu{ ArrayList<MenuItem> menuItems = new ArrayList<>(); public PancakeHouseMenu() { menuItems.add(new MenuItem("pancake1", 23)); menuItems.add(new MenuItem("pancake2", 13)); menuItems.add(new MenuItem("pancake3", 45)); } @Override public Iterator createIterator() { return menuItems.iterator(); }}public class CafeMenu implements Menu{ Hashtable menuItems = new Hashtable<>(); public CafeMenu() { MenuItem menuItem = new MenuItem("cafe1", 37); menuItems.put(menuItem.getName(), menuItem); menuItem = new MenuItem("cafe2", 87); menuItems.put(menuItem.getName(), menuItem); menuItem = new MenuItem("cafe3", 23); menuItems.put(menuItem.getName(), menuItem); } @Override public Iterator createIterator() { //返回HashTable的迭代器 return menuItems.values().iterator(); }}
3-Iterator
/** * DinerMenu的迭代器:DinerMenu中数据用数组存储,需要实现该迭代器 * */public class DinerMenuIterator implements Iterator{ MenuItem menuItems[]; int position = 0; public DinerMenuIterator(MenuItem menuItems[]) { this.menuItems = menuItems; } public boolean hasNext() { if(position >= menuItems.length || menuItems[position] == null) { return false; }else { return true; } } @Override public Object next() { MenuItem menuItem = menuItems[position]; position++; return menuItem; }}
4-服务员和测试
服务员遍历菜单,通过菜单的迭代器显示出所有菜品的菜名和单价。
public class Waitress { ArrayList<Menu> menuList = new ArrayList<>();//存菜单 public Waitress() { } //添加菜单 public void addMenu(Menu menu){ menuList.add(menu); } /**-------------------------------------------- * 便利所有菜单,并且将菜单内容通过Iterator显示出来 * -------------------------------------------*/ public void printMenu() { for(int i = 0; i < menuList.size(); i++) { Menu menu = menuList.get(i); Iterator iterator = menu.createIterator(); printMenu(iterator); } } //根据迭代器打印菜单内容 private void printMenu(Iterator iterator) { while(iterator.hasNext()) { MenuItem menuItem = (MenuItem) iterator.next(); System.out.println("name:"+menuItem.getName()+" price:"+menuItem.getPrice()); } }}
测试:
public class Test { public static void main(String[] args) { Waitress waitress = new Waitress(); waitress.addMenu(new CafeMenu()); waitress.addMenu(new PancakeHouseMenu()); waitress.addMenu(new DinerMenu()); waitress.printMenu(); }}
2-组合模式(Composite Pattern)
如果上面实例中DinerMenu中某个菜品是另一个餐厅的菜单,这该如何处理?因为DinerMenu中存储的数据是MenuItem,是无法和Menu一起处理的。这就需要组合模式。
1-定义
允许你将对象组合成树形结构来构成“整体/部分”的层次结构。组合能让客户一致地处理单一对象和对象组合。
2-结构
类似于树的结构,有节点和叶子节点。但是系统在出的时候把叶子节点看做没有分支的节点。
1. Compoent(组件)-包含叶子节点和节点的所有操作。
2. Composite(组合,节点,extends Component)-实现属于节点的操作
3. Leaf(叶子节点,extends Component)-实现叶子节点的操作
4. 将叶子节点和节点组成最终的ALL节点。形成一棵树,而ALL节点就是树根。
5. 对树根进行操作,会将Leaf和Composite都当做Compoent一起处理。
3-实例代码
1-Component
public abstract class MenuComponent { /*------------------- * Composite methods *-------------------*/ public void add(MenuComponent menuComponent) { throw new UnsupportedOperationException(); } public void remove(MenuComponent menuComponent) { throw new UnsupportedOperationException(); } public MenuComponent getChild(int i){ throw new UnsupportedOperationException(); } /*----------------------- * Operations by MenuItem *-----------------------*/ public String getName() { throw new UnsupportedOperationException(); } public int getPrice() { throw new UnsupportedOperationException(); } //operation both Menu and MenuItem public void print() { throw new UnsupportedOperationException(); }}
2-Composite
实现Menu的几个方法。
public class Menu extends MenuComponent{ ArrayList<MenuComponent> menuComponentList = new ArrayList<>(); String name; public Menu(String name) { this.name = name; } public void add(MenuComponent menuComponent) { menuComponentList.add(menuComponent); } public void remove(MenuComponent menuComponent) { menuComponentList.remove(menuComponent); } public MenuComponent getChild(int i) { return menuComponentList.get(i); } public String getName() { return name; } public void print() { System.out.println("Menu Name:"+name); System.out.println("--------------"); Iterator iterator = menuComponentList.iterator(); while(iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent) iterator.next(); menuComponent.print(); } System.out.println("--------------"); }}
3-Leaf
//实现MenuItem应该实现的方法public class MenuItem extends MenuComponent{ String name; int price; public MenuItem(String name,int price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public void print() { System.out.println("name:"+name+" price:"+price); }}
4-对树根操作
public class Waitress { MenuComponent allMenus; public Waitress(MenuComponent allMenus) { this.allMenus = allMenus; } public void printMenu() { allMenus.print(); }}
5-测试
public class Test { public static void main(String[] args) { MenuComponent pancakeMenu = new Menu("PancakeMenu"); MenuComponent dinerMenu = new Menu("DinerMenu"); MenuComponent cafeMenu = new Menu("CafeMenu"); MenuComponent dessertMenu = new Menu("DessertMenu"); MenuComponent allMenus = new Menu("all Menus"); allMenus.add(pancakeMenu); allMenus.add(cafeMenu); allMenus.add(dinerMenu); pancakeMenu.add(new MenuItem("pancake1", 11)); pancakeMenu.add(new MenuItem("pancake2", 21)); pancakeMenu.add(new MenuItem("pancake3", 31)); dinerMenu.add(new MenuItem("diner1", 32)); dinerMenu.add(new MenuItem("diner2", 56)); dinerMenu.add(new MenuItem("diner3", 89)); dessertMenu.add(new MenuItem("dessert1", 23)); dessertMenu.add(new MenuItem("dessert2", 53)); dessertMenu.add(new MenuItem("dessert3", 92)); cafeMenu.add(new MenuItem("cafe1", 2)); cafeMenu.add(dessertMenu); cafeMenu.add(new MenuItem("cafe2", 9)); Waitress waitress = new Waitress(allMenus); waitress.printMenu(); }}
4-组合和迭代器结合
给MenuCompoent增加createIterator()
方法
public Iterator createIterator(){ throw new UnsupportedOperationException(); }
在Menu和MenuItem中实现
public Iterator createIterator() { return new CompositeIterator(menuComponentList.iterator()); }
//Item没有迭代器 public Iterator createIterator() { return new NullIterator(); }
实现迭代器
public class CompositeIterator implements Iterator{ Iterator iterator; ArrayList<MenuComponent> componentList; public CompositeIterator(Iterator iterator) { this.iterator = iterator; componentList = new ArrayList<>(); saveAll(iterator); } //将所有叶子节点加入链表 private void saveAll(Iterator iterator) { while(iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent) iterator.next(); //componentList.add(menuComponent); //菜单 if(menuComponent instanceof Menu) { saveAll(menuComponent.createIterator()); } else { componentList.add(menuComponent); //将叶子加入 } } } @Override public boolean hasNext() { return (componentList.size() == 0 ? false : true); } @Override public Object next() { MenuComponent component = componentList.get(0); componentList.remove(0); return component; }}
Waitress
public class Waitress { MenuComponent allMenus; public Waitress(MenuComponent allMenus) { this.allMenus = allMenus; } public void printMenu() { Iterator iterator = allMenus.createIterator(); while(iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent) iterator.next(); menuComponent.print(); } }}
测试代码不变,直接调用waitress的printMenu()即可
5-组合模式优点
能够让客户可以处理多个对象,而不需要知道对象实际的类型。
- 迭代器模式和组合模式-《Head First 设计模式》
- First-Head:迭代器模式和组合模式
- 《Head First 设计模式》组合模式
- <Head First 设计模式>:组合模式:Component
- Head First 设计模式(九)迭代器与组合模式
- 调侃《Head First设计模式》之迭代器和组合模式(一)
- 调侃《Head First设计模式》之迭代器和组合模式(二)
- Head First 设计模式
- Head-first设计模式
- head first 设计模式
- head first 设计模式
- Head First 设计模式
- 《Head First 设计模式》
- Head First设计模式
- Head First《设计模式》
- 《Head First设计模式》
- Head First设计模式
- Head First设计模式-迭代器模式
- python raw字符串抑制转义
- centos 7 系统下进行多服务器的SSH免密码登录配置
- Sorting It All Out poj 1094(判断严格小于关系&判断是否有环)
- Swift UIBezierPath圆角
- linux中利用shell脚本条件执行命令
- 迭代器模式和组合模式-《Head First 设计模式》
- 数据结构实验之图论二:图的基于邻接矩阵的深度遍历
- 哎,我又花钱了
- composer 脚本
- Oracle 递归运行原理
- 数据结构实验之图论三:判断可达性
- 基于Hadoop HA的Hbase集群搭建(权威)
- Learn Django 2
- linux常用命令