introduction:
迭代器模式:
提供一个方法顺序访问一个聚合对象的各个元素,而又不暴露其内部的表示。
如果有一个统一的办法访问聚合中的每一个对象,你就可以编写多态的代码和这些聚合搭配。
元素之间游走的任务交给迭代器,而不是聚合对象。这不仅让聚合的接口和实现变得更简洁,也让聚合更专注在管理对象集合上。
demo:
1.模拟自己一天的三餐菜单
description:迭代器模式对外提供统一的接口,迭代不同的对象可能使用不同的方法,因此,对于我来说一天三餐,可能更多,而每一餐的菜单是不一样的,比如说早上我的菜单是用数组存储的,中午时用ArrayList存储的,晚上使用Hashtable存储的。而对外我需要提供一个同一个的接口,让别人通过这个同一个的接口来查看我的菜单。
MenuItem.java
/**
* 用于描述菜单
*/
public class MenuItem {
private String name;
private Double price;
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the price
*/
public Double getPrice() {
return price;
}
/**
* @param price the price to set
*/
public void setPrice(Double price) {
this.price = price;
}
/**
* @param name
* @param price
*/
public MenuItem(String name, Double price) {
this.name = name;
this.price = price;
}
}
Menu.java
/**
* 提供统一的菜单接口
*/
public interface Menu<T> {
Iterator<T> createIterator();
}
BreakfastMenu.java
/**
* 早餐菜单采用数组实现
*/
public class BreakfastMenu implements Menu<MenuItem>{
private static final Integer ITEM_MAX = 6;
private MenuItem[] items;
private Integer position = 0;
public BreakfastMenu(){
items = new MenuItem[ITEM_MAX];
addItem("牛奶",2.0);
addItem("面包",3.0);
}
public void addItem(String name,Double price){
MenuItem menuItem = new MenuItem(name,price);
if(position >= ITEM_MAX){
System.err.println("点餐已达极限!");
}else{
items[position] = menuItem;
position += 1;
}
}
@Override
public Iterator<MenuItem> createIterator() {
return new BreakfastMenuIterator(items);
}
}
LunchMenu.java
/**
* 午饭菜单采用ArrayList存储
*/
public class LunchMenu implements Menu<MenuItem>{
private ArrayList<MenuItem> menus ;
public LunchMenu(){
menus = new ArrayList<MenuItem>();
addItem("鸡块",5.00);
addItem("莴苣炒鸡丁",4.00);
addItem("紫菜汤",0.00);
addItem("菠菜烧鸡蛋",2.00);
}
public void addItem(String name,Double price){
MenuItem item = new MenuItem(name,price);
menus.add(item);
}
@Override
public Iterator<MenuItem> createIterator() {
return menus.iterator();
}
}
DinnerMenu.java
/**
*晚餐采用Hashtable存储
*/
public class DinnerMenu implements Menu<MenuItem>{
private Hashtable<String,MenuItem> menus;
public DinnerMenu(){
menus = new Hashtable<String,MenuItem>();
addItem("红烧鳊鱼",5.00);
addItem("青菜烧咸肉",4.00);
}
public void addItem(String name,Double price){
MenuItem item = new MenuItem(name,price);
menus.put(item.getName(), item);
}
@Override
public Iterator<MenuItem> createIterator() {
return menus.values().iterator();
}
}
由于ArrayList、Hashtable都已经实现了Iterator接口,因此都可以直接实现迭代功能,对于数组来说没有,因此,需要手工实现。
BreakfastMenuIterator.java
/**
* 早餐采用数组形式存储,因此需要实现Iterator接口,重写相关方法
*/
public class BreakfastMenuIterator implements Iterator<MenuItem>{
private MenuItem[] items;
private Integer position = 0;
public BreakfastMenuIterator(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 += 1;
return menuItem;
}
@Override
public void remove() {
if(position <= 0){
throw new IllegalStateException("该元素不存在");
}
if(items[position-1] != null){
for(int i=position-1;i<items.length;i++){
items[i] = items[i+1];
}
items[items.length-1] = null;
}
}
}
服务员类,主要作用是管理三餐
Service.java
public class Service {
private ArrayList menus;
public Service(ArrayList menus){
this.menus = menus;
}
public void printMenu(){
Iterator<Menu> menuIterator = menus.iterator();
while(menuIterator.hasNext()){
Menu menu = (Menu)menuIterator.next();
printMenu(menu.createIterator());
}
}
public void printMenu(Iterator<MenuItem> iterator){
while(iterator.hasNext()){
MenuItem menuItem = iterator.next();
System.out.println(menuItem.getName()+",");
System.out.println(menuItem.getPrice());
}
System.out.println();
}
}
Test.java
public class Test {
public static void main(String[] args) {
//1.实例化三餐
Menu<MenuItem> breakfast = new BreakfastMenu();
Menu<MenuItem> lunch = new LunchMenu();
Menu<MenuItem> dinner = new DinnerMenu();
//2.将三餐添加到ArrayList中
ArrayList<Menu> list = new ArrayList<Menu>();
list.add(breakfast);
list.add(lunch);
list.add(dinner);
Service service = new Service(list);
service.printMenu();
}
}
输出结果:
牛奶,
2.0
面包,
3.0
鸡块,
5.0
莴苣炒鸡丁,
4.0
紫菜汤,
0.0
菠菜烧鸡蛋,
2.0
青菜烧咸肉,
4.0
红烧鳊鱼,
5.0
在迭代器设计模式中,我们遇到了一个OO设计原则-单一责任原则
单一责任原则:
一个类应该只有一个引起变化的原因
类的每个责任都有改变的潜在区域,超过一个责任,意味着超过一个改变区域。
这个原则告诉我们,尽量让每个类保持单一责任。
我们知道要避免类内的改变,因为修改代码很容易造成许多潜在的错误。
内聚是用来衡量一个类或模块紧密地达到单一目的或责任。
当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚;反之,当被设计成支持一组不相关的功能时,我们说它是低内聚。