设计模式学习(九) 迭代器模式
引入
定义:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示
uml类图
这个模式提供了一种方法,可以顺序访问一个聚集对象中的元素,而又不用知道内部是如何表示的。
迭代器模式把在元素之间游走的职责交给迭代器,而不是聚合对象。这不仅让聚合的接口和实现变得更简洁,也可以让聚合更专注在它所应该专注的事情上面(也就是管理对象集合),而不必理会遍历的事情。
迭代器模式角色:
Iterator:迭代器接口
迭代器接口负责定义、访问和遍历元素的接口。
ConcreteIterator:具体迭代器类
具体迭代器类的目的主要是实现迭代器接口,并记录遍历的当前位置。
Aggregate:容器接口
容器接口负责提供创建具体迭代器角色的接口。
ConcreteAggregate:具体容器类
具体迭代器角色与该容器相关联。
Client:客户类
示例
package com.zpkj.project17;
public class MenuItem {
String name;
String description;
/**
* 是否是素食
*/
boolean vegetarian;
double price;
protected MenuItem(String name, String description, boolean vegetarian, double price) {
super();
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
package com.zpkj.project17;
public interface MyIterator<E> {
boolean hasNext();
E next();
}
package com.zpkj.project17;
import java.util.ArrayList;
public class PancakeHouseMenuIterator implements MyIterator<Object>{
ArrayList<MenuItem> menuItems;
int position=0;
protected PancakeHouseMenuIterator(ArrayList<MenuItem> menuItems) {
super();
this.menuItems = menuItems;
}
@Override
public boolean hasNext() {
if(position>=menuItems.size() || menuItems.get(position)==null){
return false;
}else {
return true;
}
}
@Override
public Object next() {
MenuItem menuItem = menuItems.get(position);
position++;
return menuItem;
}
}
package com.zpkj.project17;
public class DinerMenuIterator implements MyIterator<Object> {
MenuItem[] menuItems;
int position = 0;
protected DinerMenuIterator(MenuItem[] menuItems) {
super();
this.menuItems = menuItems;
}
@Override
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;
}
}
package com.zpkj.project17;
public interface CreateIterator {
MyIterator<Object> createMyIterator();
}
package com.zpkj.project17;
import java.util.Arrays;
/**
* 午餐菜单
*/
public class DinerMenu implements CreateIterator{
static final int MAX_ITEMS = 6;
int numberOfItems = 0;
MenuItem[] menuItems;
public DinerMenu() {
super();
menuItems = new MenuItem[MAX_ITEMS];
addItem("Vegetarian BLT", "描述", true, 2.99);
addItem("Vegetarian BLT", "描述", true, 2.99);
addItem("Vegetarian BLT", "描述", true, 2.99);
addItem("Vegetarian BLT", "描述", true, 2.99);
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem =new MenuItem(name, description, vegetarian, price);
if(numberOfItems>=6){
System.out.println("sorry,menu is full!can't add item to menu");
}else {
menuItems[numberOfItems] = menuItem;
numberOfItems++;
}
}
public MenuItem[] getMenuItems() {
return menuItems;
}
public MyIterator<Object> createMyIterator(){
return new DinerMenuIterator(menuItems);
}
@Override
public String toString() {
return "DinerMenu [numberOfItems=" + numberOfItems + ", menuItems=" + Arrays.toString(menuItems) + "]";
}
}
package com.zpkj.project17;
import java.util.ArrayList;
/**
* 煎饼屋菜单
*/
public class PancakeHouseMenu implements CreateIterator{
ArrayList<MenuItem> menuItems;
public PancakeHouseMenu() {
super();
menuItems = new ArrayList<MenuItem>();
addItem("K&B's Pancake Breakfast", "Pancakes whih scrambled eggs, and toast", true, 2.99);
addItem("Regular Pancake Breakfast", "Pancakes whih fired eggs, sausage", false, 2.99);
addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
addItem("Waffles", "whih your choice of blueberries or strawberries", true, 3.59);
}
public void addItem(String name,String description,boolean vegetarian,double price){
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public ArrayList<MenuItem> getMenuItems() {
return menuItems;
}
@Override
public String toString() {
return "PancakeHouseMenu [menuItems=" + menuItems + "]";
}
@Override
public MyIterator<Object> createMyIterator() {
return new PancakeHouseMenuIterator(menuItems);
}
}
package com.zpkj.project17;
public class Waitress {
CreateIterator DinerMenuIterator;
CreateIterator DinerMenu;
public Waitress( PancakeHouseMenu DinerMenuIterator, DinerMenu DinerMenu) {
this.DinerMenuIterator = DinerMenuIterator;
this.DinerMenu = DinerMenu;
}
public void printMenu(){
MyIterator<Object> createIterator = DinerMenuIterator.createMyIterator();
MyIterator<Object> createMyIterator = DinerMenu.createMyIterator();
printMenuIterator(createIterator);
System.out.println("-------------");
printMenuIterator(createMyIterator);
}
void printMenuIterator(MyIterator<Object> iterator){
while (iterator.hasNext()) {
MenuItem item = (MenuItem)iterator.next();
System.out.println(item.getName());
System.out.println(item.getDescription());
System.out.println(item.getPrice());
}
}
}
结果
oo原则
单一原则:一个类应该只有一个引起变化的原因,尽量让每个类保持单一职责
内聚:用来度量一个类或模块紧密地达到单一目的或职责。
当一个模块或一个类被设计成只支持一组相关的功能时,我们说它具有高内聚;反之,当被设计成支持一组不相关的功能时,我们说它具有低内聚。
内聚是一个比单一责任原则更普遍的概念,但两者其实关系是很密切的。遵循这个原则的类容易具有很高的凝聚力,而且比背负许多职责的低内聚类更容易维护。
总结
1.迭代器允许访问聚合的元素,而不需要暴露它的内部结构
2.迭代器将遍历聚合的工作封装进一个对象中
3.当使用迭代器的时候,我们依赖聚合提供的遍历
4.迭代器提供了一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态
5.我们应该努力让一个类只分配一个责任。