两种类型的菜单,第一种菜单中的每一项都是ArrayList的元素,而第二种菜单中的每一项是数组元素。如何对这两种菜单统一操作呢?
package javaapplication39;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
PancakeBouseMenu menu = new PancakeBouseMenu();
menu.listMenu();
System.out.println("-----------------------");
DinerMenu menu2 = new DinerMenu();
menu2.listMenu();
}
}
class MenuItem { //菜单中的每一项
String name;
String description;
boolean vegetarian;
int price;
public MenuItem(String name, String description, boolean vegetarian, int price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
String getName() {
return name;
}
String getDescription() {
return description;
}
boolean isVegetarian() {
return vegetarian;
}
int getPrice() {
return price;
}
public void showItem() {
System.out.println(getName() + ":" + getDescription() + " " + getPrice() + " | " + getVegetarian());
}
private String getVegetarian() {
if (isVegetarian() == true) {
return "Is Vegetarian";
}
else {
return "Not Vegetarian";
}
}
}
class PancakeBouseMenu { //第一种方式的菜单,是由ArrayList把每一项连接起来的
ArrayList<MenuItem> menuItems;
MenuItem menuItem;
public PancakeBouseMenu() {
menuItems = new ArrayList<MenuItem>();
addItem("K&B", "Pancake and scrambled", true, 29);
addItem("Waffles", "Waffles with blueberries", true, 39);
addItem("Rregular", "Regular pancake breakefast", false, 10);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public void listMenu() {
for (int i = 0; i < menuItems.size(); i++) {
menuItems.get(i).showItem();
}
}
}
class DinerMenu { //第二中方式的菜单,数组
final int MAX_SIZE = 2;
MenuItem[] menuItems;
int location;
public DinerMenu() {
menuItems = new MenuItem[MAX_SIZE];
location = 0;
addItem("BLT", "Bacon with Lettuce and Tomato", true, 21);
addItem("HotDog", "a hot dog with relish", false, 39);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
if (location < MAX_SIZE) {
menuItems[location] = new MenuItem(name, description, vegetarian, price);
location++;
}
else {
System.out.println("OUT OF MAX_SIZE");
}
}
public void listMenu() {
for (int i = 0; i < MAX_SIZE; i++) {
menuItems[i].showItem();
}
}
}
黄颜色标注的两个listMenu其实做的事情相同,只是处理的元素种类不同。如果我们还想“列出所有的蔬菜”,“列出所有价格少于XX的菜”。。。那么,DinnerMenu和PancakeMenu里面那又要多出很多相似的方法。可不可以封装呢?比如把这些相似的方法写在它们共同的抽象父类里面,或者放在一个façade类里面?
Iterator pattern 隆重登场:Iterator Pattern是什么?就是为处理各种Collection的类写一个通用接口。通过一个类似于adapter 的类的中转,该接口与处理Collection的类相联系。
看看下面的程序,注意:我们这个Iterator接口是我们自己写的,不是java库里的那个。
package javaapplication39;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
PancakeBouseMenu pmenu = new PancakeBouseMenu();
Iterator iterator = pmenu.createPancakeIterator();
while (iterator.hasNext()) {
iterator.next().showItem();
}
DinerMenu dmenu = new DinerMenu();
iterator = dmenu.createDinnerIterator();
while (iterator.hasNext()) {
iterator.next().showItem();
}
}
}
class MenuItem { //菜单中的每一项
String name;
String description;
boolean vegetarian;
int price;
public MenuItem(String name, String description, boolean vegetarian, int price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
String getName() {
return name;
}
String getDescription() {
return description;
}
boolean isVegetarian() {
return vegetarian;
}
int getPrice() {
return price;
}
public void showItem() {
System.out.println(getName() + ":" + getDescription() + " " + getPrice() + " | " + getVegetarian());
}
private String getVegetarian() {
if (isVegetarian() == true) {
return "Is Vegetarian";
}
else {
return "Not Vegetarian";
}
}
}
interface Iterator {//通用接口
public boolean hasNext();
public MenuItem next();
}
class PancakeIterator implements Iterator {//Adapter和Façade功能的混合体
ArrayList<MenuItem> menuItems;
int location;
PancakeIterator(ArrayList<MenuItem> menuItems) {
this.menuItems = menuItems;
location = 0;
}
public boolean hasNext() {
if (location >= menuItems.size() || menuItems.get(location) == null) {
return false;
}
else {
return true;
}
}
public MenuItem next() {
MenuItem menuItem = menuItems.get(location);
location++;
return menuItem;
}
}
class DinerIterator implements Iterator {
MenuItem[] menuItems;
int location;
DinerIterator(MenuItem[] menuItems) {
this.menuItems = menuItems;
location = 0;
}
public boolean hasNext() {
if (location >= menuItems.length || menuItems[location] == null) { //这个“或”符号的两边写反了,就会抛出数组越界异常
return false;
}
else {
return true;
}
}
public MenuItem next() {
MenuItem menuItem = menuItems[location];
location++;
return menuItem;
}
}
class PancakeBouseMenu { //第一种方式的菜单,是由ArrayList把每一项连接起来的
ArrayList<MenuItem> menuItems;
public PancakeBouseMenu() {
menuItems = new ArrayList<MenuItem>();
addItem("K&B", "Pancake and scrambled", true, 29);
addItem("Waffles", "Waffles with blueberries", true, 39);
addItem("Rregular", "Regular pancake breakefast", false, 10);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public Iterator createPancakeIterator() {
return new PancakeIterator(menuItems);
}
}
class DinerMenu { //第二种方式的菜单,数组
final int MAX_SIZE = 2;
MenuItem[] menuItems;
int location;
public DinerMenu() {
menuItems = new MenuItem[MAX_SIZE];
location = 0;
addItem("BLT", "Bacon with Lettuce and Tomato", true, 21);
addItem("HotDog", "a hot dog with relish", false, 39);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
if (location < MAX_SIZE) {
menuItems[location] = new MenuItem(name, description, vegetarian, price);
location++;
}
else {
System.out.println("OUT OF MAX_SIZE");
}
}
public Iterator createDinnerIterator() {
return new DinerIterator(menuItems);
}
}
最后,我们把DinnerMenu和PancakeMenu中的功能类似的createXXXIterator()方法提取出来,放到新建的接口Menu里面去:
package javaapplication39;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Menu pmenu = new PancakeBouseMenu();
Iterator iterator = pmenu.createIterator();
while (iterator.hasNext()) {
iterator.next().showItem();
}
Menu dmenu = new DinerMenu();
iterator = dmenu.createIterator();
while (iterator.hasNext()) {
iterator.next().showItem();
}
}
}
class MenuItem { //菜单中的每一项
String name;
String description;
boolean vegetarian;
int price;
public MenuItem(String name, String description, boolean vegetarian, int price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
String getName() {
return name;
}
String getDescription() {
return description;
}
boolean isVegetarian() {
return vegetarian;
}
int getPrice() {
return price;
}
public void showItem() {
System.out.println(getName() + ":" + getDescription() + " " + getPrice() + " | " + getVegetarian());
}
private String getVegetarian() {
if (isVegetarian() == true) {
return "Is Vegetarian";
}
else {
return "Not Vegetarian";
}
}
}
interface Iterator {//通用接口
public boolean hasNext();
public MenuItem next();
}
class PancakeIterator implements Iterator {//Adapter和Façade功能的混合体
ArrayList<MenuItem> menuItems;
int location;
PancakeIterator(ArrayList<MenuItem> menuItems) {
this.menuItems = menuItems;
location = 0;
}
public boolean hasNext() {
if (location >= menuItems.size() || menuItems.get(location) == null) {
return false;
}
else {
return true;
}
}
public MenuItem next() {
MenuItem menuItem = menuItems.get(location);
location++;
return menuItem;
}
}
class DinerIterator implements Iterator {
MenuItem[] menuItems;
int location;
DinerIterator(MenuItem[] menuItems) {
this.menuItems = menuItems;
location = 0;
}
public boolean hasNext() {
if (location >= menuItems.length || menuItems[location] == null) { //这个“或”符号的两边写反了,就会抛出数组越界异常
return false;
}
else {
return true;
}
}
public MenuItem next() {
MenuItem menuItem = menuItems[location];
location++;
return menuItem;
}
}
interface Menu {
Iterator createIterator();
}
class PancakeBouseMenu implements Menu { //第一种方式的菜单,是由ArrayList把每一项连接起来的
ArrayList<MenuItem> menuItems;
public PancakeBouseMenu() {
menuItems = new ArrayList<MenuItem>();
addItem("K&B", "Pancake and scrambled", true, 29);
addItem("Waffles", "Waffles with blueberries", true, 39);
addItem("Rregular", "Regular pancake breakefast", false, 10);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public Iterator createIterator() {
return new PancakeIterator(menuItems);
}
}
class DinerMenu implements Menu { //第二种方式的菜单,数组
final int MAX_SIZE = 2;
MenuItem[] menuItems;
int location;
public DinerMenu() {
menuItems = new MenuItem[MAX_SIZE];
location = 0;
addItem("BLT", "Bacon with Lettuce and Tomato", true, 21);
addItem("HotDog", "a hot dog with relish", false, 39);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
if (location < MAX_SIZE) {
menuItems[location] = new MenuItem(name, description, vegetarian, price);
location++;
}
else {
System.out.println("OUT OF MAX_SIZE");
}
}
public Iterator createIterator() {
return new DinerIterator(menuItems);
}
}
Java中的Collection类型不仅包括数组,ArrayList,还有hastTable, Queue, 等等。Java API中本身就有自带的Iterator接口,以及让这些类型返回一个Iterator型的函数。只是Java API的Iterator接口不仅有hasnext(), next()函数,还有一个remove()函数需要子类实现之。
package javaapplication39;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
Menu pmenu = new PancakeBouseMenu();
Iterator iterator = pmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
Menu dmenu = new DinerMenu();
iterator = dmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
Menu cmenu = new CafeMenu();
iterator = cmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
}
}
class MenuItem { //菜单中的每一项
String name;
String description;
boolean vegetarian;
int price;
public MenuItem(String name, String description, boolean vegetarian, int price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
String getName() {
return name;
}
String getDescription() {
return description;
}
boolean isVegetarian() {
return vegetarian;
}
int getPrice() {
return price;
}
public void showItem() {
System.out.println(getName() + ":" + getDescription() + " " + getPrice() + " | " + getVegetarian());
}
private String getVegetarian() {
if (isVegetarian() == true) {
return "Is Vegetarian";
}
else {
return "Not Vegetarian";
}
}
}
class DinerIterator implements Iterator { //数组不能返回一个Iterator类型,所以只能手写
MenuItem[] menuItems;
int location;
DinerIterator(MenuItem[] menuItems) {
this.menuItems = menuItems;
location = 0;
}
public boolean hasNext() {
if (location >= menuItems.length || menuItems[location] == null) { //这个“或”符号的两边写反了,就会抛出数组越界异常
return false;
}
else {
return true;
}
}
public MenuItem next() {
MenuItem menuItem = menuItems[location];
location++;
return menuItem;
}
public void remove() { //Java API中的Iterator还有Remove函数需要实现
for (int i = location - 1; i < menuItems.length - 1; i++) {
menuItems[i] = menuItems[i + 1];
}
menuItems[menuItems.length - 1] = null;
}
}
interface Menu {
Iterator createIterator();
}
class PancakeBouseMenu implements Menu { //第一种方式的菜单,是由ArrayList把每一项连接起来的
ArrayList<MenuItem> menuItems;
public PancakeBouseMenu() {
menuItems = new ArrayList<MenuItem>();
addItem("K&B", "Pancake and scrambled", true, 29);
addItem("Waffles", "Waffles with blueberries", true, 39);
addItem("Rregular", "Regular pancake breakefast", false, 10);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
public Iterator createIterator() {
return menuItems.iterator(); //直接利用ArrayList中的iterator函数,转化ArrayList为Iterator型
}
}
class DinerMenu implements Menu { //第二种方式的菜单,数组
final int MAX_SIZE = 2;
MenuItem[] menuItems;
int location;
public DinerMenu() {
menuItems = new MenuItem[MAX_SIZE];
location = 0;
addItem("BLT", "Bacon with Lettuce and Tomato", true, 21);
addItem("HotDog", "a hot dog with relish", false, 39);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
if (location < MAX_SIZE) {
menuItems[location] = new MenuItem(name, description, vegetarian, price);
location++;
}
else {
System.out.println("OUT OF MAX_SIZE");
}
}
public Iterator createIterator() {
return new DinerIterator(menuItems);//数组,没办法,还是只能手动写
}
}
class CafeMenu implements Menu {
Hashtable menuItems;
public CafeMenu() {
menuItems = new Hashtable();
addItem("Veggie Burger", "Veggie Burger on a whole bun", true, 30);
addItem("Soup of the Day", "a cup of soap of the day", false, 36);
}
public void addItem(String name, String description, boolean vegetarian, int price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.put(name, menuItem);
}
public Iterator createIterator() {
return menuItems.values().iterator();//HashTable也可以直接转化成Iterator型
}
}
看到主函数用到三个同样的循环,我们把显示各种Menu的功能放到一个Waitress类中去:
public class Main {
public static void main(String[] args) {
Menu pmenu = new PancakeBouseMenu();
Menu dmenu = new DinerMenu();
Menu cmenu = new CafeMenu();
Waitress waitress = new Waitress();
waitress.printMenu(pmenu, dmenu, cmenu);
}
}
class Waitress {
public void printMenu(Menu pmenu, Menu dmenu, Menu cmenu) {
Iterator iterator = pmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
iterator = dmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
iterator = cmenu.createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
}
}
如果我们需要再新添一个TeaMenu呢?那么Waitress里面的printMenu方法的参数又要添加一个。可不可以把所有的CafeMenu, PancakeMenu, DinnerMenu组成ArrayList,当作参数传到printMenu方法里面去呢?
public class Main {
public static void main(String[] args) {
Menu pmenu = new PancakeBouseMenu();
Menu dmenu = new DinerMenu();
Menu cmenu = new CafeMenu();
Waitress waitress = new Waitress();
waitress.addMenuToArrayList(cmenu);
waitress.printMenu();
System.out.println("---------------------------");
waitress.addMenuToArrayList(dmenu);
waitress.addMenuToArrayList(pmenu);
waitress.printMenu();
System.out.println("---------------------------");
waitress.removeMenuToArrayList(cmenu);
waitress.printMenu();
}
}
class Waitress {
ArrayList<Menu> menuList;
public Waitress() {
menuList = new ArrayList<Menu>();
}
public void printMenu() {
for (int i = 0; i < menuList.size(); i++) {
Iterator iterator = menuList.get(i).createIterator();
while (iterator.hasNext()) {
MenuItem menuItem = (MenuItem) iterator.next();
menuItem.showItem();
}
}
}
public void addMenuToArrayList(Menu menu) {
menuList.add(menu);
}
public void removeMenuToArrayList(Menu menu) {
menuList.remove(menu);
}
}