您的位置:首页 > 其它

设计模式 组合与迭代器

2018-01-04 16:16 591 查看
迭代器模式:提供一种方法顺序访问遍历一个聚合(集合)对象中的各个元素,而无需暴露其(集合)内部的实现。

组合模式: 允许将对象组成树形结构来表现“整体/部分”的层次结构,该树形结构可同时包容个别对象和组合对象。组合让客户以一致的方式处理个别对象和组合对象。组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点(无法再分)。

下面以一个实例说明:

1. 主函数

public class MenuTestDrive {

/**
* @param args
* 组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构,树形结构包含了组合以及个别对象。
* 组合能够让客户以一致的方式处理个别对象以及对象组合。迭代器模式是解决方案中的一部分。
* 组合包含组件,组件有两种:组合与叶节点元素。
*/
public static void main(String[] args) {
// TODO Auto-generated method stub

MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast");
MenuComponent dinerMenu = new Menu("DINER MENU","Lunch");
MenuComponent cafeMeun = new Menu("CAFE MENU","Dinner");
MenuComponent dessertMenu = new Menu("DESSERT MENU","Dessert of course!");
MenuComponent allMenus = new Menu("ALL MENUS","All menus combined");

System.out.println("------------------MenuTestDrive main() add differents MenuComponent to allMenus start----------------------");
try{
allMenus.add(pancakeHouseMenu);
allMenus.add(dinerMenu);
allMenus.add(cafeMeun);

dinerMenu.add(new MenuItem("Pasta",
"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
true,
3.89));
dinerMenu.add(dessertMenu);
dessertMenu.add(new MenuItem("Apple Pie",
"Apple Pie with a flakey crust, topped with vanilla ice cream",
true,
1.59));
} catch (Exception e){
e.printStackTrace();
}

System.out.println("------------------MenuTestDrive main() add differents MenuComponent to allMenus end -----------------------");
Waitress waitress = new Waitress(allMenus);
System.out.println("------------------case 1: Waitress not care of how to visit , only use MenuComponent to call interface-----");
waitress.printMenu();
System.out.println("------------------case 2: Waitress use Composite-Iterator mode to filter all 蔬菜vegetarians----------------");
waitress.printVegetarianMenu();

}

}
2.  抽象组件 MenuComponent.java
import java.util.Iterator;

public abstract class MenuComponent {

public void add(MenuComponent menuComponent)
throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public void remove(MenuComponent menuComponent)
throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public MenuComponent getChild(int i) throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public String getName() throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public String getDescription() throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public double getPrice() throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public boolean isVegetarian() throws UnsupportOperationException {
throw new UnsupportOperationException();
}

public void print() throws UnsupportOperationException {
throw new UnsupportOperationException();
}

abstract Iterator createIterator();
}3. 抽象组件的子类:叶节点MenuItem 和组合Menu 
3.1 叶节点组件MenuItem.java

 import java.util.Iterator;

public class MenuItem extends MenuComponent {

String name;
String description;
boolean vegetarian;
double price;

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

public String getName() throws UnsupportOperationException {
// TODO Auto-generated method stub
return name;
}

public String getDescription() throws UnsupportOperationException {
// TODO Auto-generated method stub
return description;
}

public double getPrice() throws UnsupportOperationException {
// TODO Auto-generated method stub
return price;
}

public boolean isVegetarian() throws UnsupportOperationException {
// TODO Auto-generated method stub
return vegetarian;
}

public void print() throws UnsupportOperationException {
// TODO Auto-generated method stub
System.out.print(" " + getName());
if (isVegetarian()) {
System.out.print(" (V) ");
}
System.out.print(" , " + getPrice());
System.out.println(" --" + getDescription());
}

Iterator createIterator() {
// TODO Auto-generated method stub
return new NullIterator();
}
}3.2 组合组件Menu.java
import java.util.ArrayList;
import java.util.Iterator;

public class Menu extends MenuComponent {

ArrayList menuComponents = new ArrayList();
String name;
String description;

public Menu(String name, String description) {
this.name = name;
this.description = description;
}

public void add(MenuComponent menuComponent)
throws UnsupportOperationException {
// TODO Auto-generated method stub
menuComponents.add(menuComponent);
}

public void remove(MenuComponent menuComponent)
throws UnsupportOperationException {
// TODO Auto-generated method stub
menuComponents.remove(menuComponent);
}

public MenuComponent getChild(int i) throws UnsupportOperationException {
// TODO Auto-generated method stub
return (MenuComponent) menuComponents.get(i);
}

public String getName() throws UnsupportOperationException {
// TODO Auto-generated method stub
return name;
}

public String getDescription() throws UnsupportOperationException {
// TODO Auto-generated method stub
return description;
}

public void print() throws UnsupportOperationException {
// TODO Auto-generated method stub
System.out.print("\n" + getName());
System.out.println(" ," + getDescription());
System.out.println(" ----------------");

// 如果我们想要女招待可以使用迭代器变流器整个组合,就不需要在此处使用迭代器遍历,要交给女招待
Iterator it = menuComponents.iterator();
while (it.hasNext()) {
MenuComponent menuCompent = (MenuComponent) it.next();
menuCompent.print();
}
}

// 为了女招待使用迭代器遍历组合,创建该接口
Iterator createIterator() {
// TODO Auto-generated method stub
return new CompositeIterator(menuComponents.iterator());
}

}
4.  实现Iterator迭代器的子类NullIterator.java和CompositeIterator.java
4.1  叶子节点使用createIterator创建NullIterator 迭代器

import java.util.Iterator;

public class NullIterator implements Iterator {

public boolean hasNext() {
// TODO Auto-generated method stub
return false;
}

public Object next() {
// TODO Auto-generated method stub
return null;
}

public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

}

4.2 组合组件使用createIterator创建CompositeIterator 迭代器
  该迭代器可遍历组合组件内的所有组件(叶子节点组件和组合组件,子组合组件....)

import java.util.Iterator;
import java.util.Stack;
import java.util.function.Consumer;

// 这是我们创建的便于女招待使用迭代器遍历组合的“组合迭代器”类
// 它的工作是遍历组件内的菜单项,并确保所有的子菜单(以及子子菜单....)都被包括进来
public class CompositeIterator implements Iterator {

Stack stack = new Stack();

// iterator参数是 Menu对象(组合)中的成员ArrayList对象取
4000
得的迭代器
public CompositeIterator(Iterator iterator) {
stack.push(iterator);
}

public boolean hasNext() {
// TODO Auto-generated method stub
if (stack.isEmpty()) {
return false;
} else {
Iterator iterator = (Iterator) stack.peek(); // 取出来这个迭代器偷看一下
if (iterator.hasNext()) {
return true;
} else {
stack.pop(); // 将遍历完的迭代器对象弹出堆栈
return hasNext();
}
}
}

public Object next() {
// TODO Auto-generated method stub
if (hasNext()) {
Iterator iterator = (Iterator) stack.peek(); // 取出堆栈存放的迭代器偷看一下
MenuComponent component = (MenuComponent) iterator.next();// 取出该位置对象,并将位置移动到下一个
if (component instanceof Menu) {
stack.push(component.createIterator()); // 如果是子菜单(组合类型),把将要遍历的下一个迭代器对象放入到堆栈,为了下一步的遍历
}
return component;
}
return null;
}

public void remove() {
// TODO Auto-generated method stub
throw new UnsupportedOperationException();
}

}
5. 自定义异常类UnsupportOperationException
public class UnsupportOperationException extends Exception {

private static final long serialVersionUID = 1L;

UnsupportOperationException() {
}
}
6. 女招待对象Waitress,她有两种需求:不关注一个个去遍历,调用组合组件的接口一次完成;关注如何使用迭代器访问,并筛选出叶子节点做相应operation

import java.util.Iterator;

public class Waitress {
MenuComponent allMenus;

public Waitress(MenuComponent allMenus) {
this.allMenus = allMenus;
}

// 这个接口是女招待调用打印接口,实际是在组合内部打印方法调用迭代器的,女招待不能随意取出任何
public void printMenu() {
try {
allMenus.print();
} catch (UnsupportOperationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

// 这个接口是用让女招待使用迭代器去遍历组合的,可以随意取出对象
public void printVegetarianMenu() {
Iterator iterator = allMenus.createIterator();
System.out.println("\n VEGETARIAN MENU\n----");
while (iterator.hasNext()) {
MenuComponent menuCompent = (MenuComponent) iterator.next();
try {
if (menuCompent.isVegetarian()) {
menuCompent.print();
}
} catch (UnsupportOperationException e) {
// TODO Auto-generated catch block
// e.printStackTrace();
}

}

}
}


7. 类结构层次:
Menu 和 MenuItem均继承 MenuComponent组件抽象类。

CompositeIterator和NullIterator均实现java内置接口 Iterator。

组合模式的树结构:

                                                                Menu

                                                    --                 --      --

                                                --                        ---          ----

                                           MenuItem            MenuItem      Menu

                                                                                           
    --

                                                                                           
--

                                                                                        MenuItem

可以无限扩张。

图片1: 结构类图   

11

111

图片2:调用图

222

2

运行后结果:

------------------MenuTestDrive main() add differents MenuComponent to allMenus start----------------------

------------------MenuTestDrive main() add differents MenuComponent to allMenus end -----------------------

------------------case 1: Waitress not care of how to visit , only use MenuComponent to call interface-----

ALL MENUS  ,All menus combined

 ----------------

PANCAKE HOUSE MENU  ,Breakfast

 ----------------

DINER MENU  ,Lunch

 ----------------

  Pasta (V)  , 3.89    --Spaghetti with Marinara Sauce, and a slice of sourdough bread

DESSERT MENU  ,Dessert of course!

 ----------------

  Apple Pie (V)  , 1.59    --Apple Pie with a flakey crust, topped with vanilla ice cream

CAFE MENU  ,Dinner

 ----------------

------------------case 2: Waitress use Composite-Iterator mode to filter all 蔬菜vegetarians----------------

 VEGETARIAN MENU

----

  Pasta (V)  , 3.89    --Spaghetti with Marinara Sauce, and a slice of sourdough bread

  Apple Pie (V)  , 1.59    --Apple Pie with a flakey crust, topped with vanilla ice cream

  Apple Pie (V)  , 1.59    --Apple Pie with a flakey crust, topped with vanilla ice cream
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: