迭代器模式
定义
迭代器模式提供一个方法顺序访问一个聚合对象中的各个元素, 而又不暴露其内部的表示
设计原则;
单一责任: 一个类应该只有一个引起变化的原因
内聚: 用来度量一个类或模块紧密的达到单一目的或责任; 当一个模块或一个类被设计成只支持一组相关的功能时, 我们说他具有高内聚
好处:**
- 使用迭代器有了一个统一的方法去访问聚合中的元素, 因此可以使用多态
- 迭代器模式把在元素之间游走的责任交给了迭代器, 而不是聚合对象, 不仅让聚合的接口和实现变得更简洁, 也可以让聚合更专注于他所应该专注的事情上面
案例
背景: 餐厅和煎饼屋合并, 煎饼屋提供早餐, 餐厅提供午餐, 其中煎饼屋菜单用ArrayList集合装菜单项, 餐厅菜单用数组来装菜单项, 侍女只需要一份菜单, 列出所有的菜单项, 如何设计系统
原始设计:
Waitress代码:
public class Waitress {
public void printMenu() {
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
List<MenuItem> menuItemList = pancakeHouseMenu.getMenuItems();
for (MenuItem menuItem : menuItemList) {
System.out.println(menuItem);
}
DinerMenu dinerMenu = new DinerMenu();
MenuItem[] menuItemsArray = dinerMenu.getMenuItems();
for (MenuItem menuItem : menuItemsArray) {
System.out.println(menuItem);
}
}
}
使用迭代器模式并优化结构后:
由于数组没有实现迭代器接口, 需要自定义迭代器
public class DinerMenuIterator implements Iterator {
private MenuItem[] menuItems;
int positon = 0;
public DinerMenuIterator(MenuItem[] menuItems) {
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if (positon >= menuItems.length || menuItems[positon] == null) {
return false;
} else {
return true;
}
}
@Override
public Object next() {
return menuItems[positon++];
}
public MenuItem[] getMenuItems() {
return menuItems;
}
public void setMenuItems(MenuItem[] menuItems) {
this.menuItems = menuItems;
}
}
Waitress代码优化
public class Waitress {
private Menu pancakeHouseMenu;
private Menu dinerMenu;
public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
this.pancakeHouseMenu = pancakeHouseMenu;
this.dinerMenu = dinerMenu;
}
public void printMenu() {
printMenu(pancakeHouseMenu.createIterator());
printMenu(dinerMenu.createIterator());
}
private void printMenu(Iterator iterator) {
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
测试:
@Test
public void testIterator() {
Waitress waitress = new Waitress(new PancakeHouseMenu(), new DinerMenu());
waitress.printMenu();
}
测试结果:
MenuItem{name='煎饼1'}
MenuItem{name='煎饼2'}
MenuItem{name='煎饼3'}
MenuItem{name='煎饼4'}
MenuItem{name='肉'}
MenuItem{name='蛋'}
MenuItem{name='菜'}
使用迭代器模式优化后:
1.菜单的实现被封装, 侍女无需知道菜单如何存储菜单项
2.将两个循环的代码抽取了出来, 调用迭代器的方法
3.侍女依赖于Menu接口, 可以使用多态, 减少了对具体类的依赖
组合模式
定义
组合模式允许你将对象组合成树形结构来表现”整体/部分”层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合
**
案例