zoukankan      html  css  js  c++  java
  • 设计模式之迭代器与组合模式(四)

    因为这系列篇幅较长,所以在这里也不进行任何铺垫,直奔主题去啦。

    利用组合设计菜单

    我们要如何在菜单上应用组合模式呢?一开始,我们需要创建一个组件接口来作为菜单和菜单项的共同接口,让我们能够用统一的做法来处理菜单和菜单项。换句话说,我们可以针对菜单或菜单项调用相同的方法。

    让我们从头来看看如何让菜单能够符合组合模式的结构:

    实现菜单组件

    好了,我们开始编写菜单组件的抽象类;请记住,菜单组件的角色是为叶节点和组合节点提供一个共同的接口。

    public abstract class MenuComponent {
       
    	public void add(MenuComponent menuComponent) {
    		throw new UnsupportedOperationException();
    	}
    	public void remove(MenuComponent menuComponent) {
    		throw new UnsupportedOperationException();
    	}
    	public MenuComponent getChild(int i) {
    		throw new UnsupportedOperationException();
    	}
      
    	public String getName() {
    		throw new UnsupportedOperationException();
    	}
    	public String getDescription() {
    		throw new UnsupportedOperationException();
    	}
    	public double getPrice() {
    		throw new UnsupportedOperationException();
    	}
    	public boolean isVegetarian() {
    		throw new UnsupportedOperationException();
    	}
    
    	public abstract Iterator<MenuComponent> createIterator();
     
    	public void print() {
    		throw new UnsupportedOperationException();
    	}
    }
    

    让我们来看菜单类。别忘了,这是组合类图里的叶类,它实现组合内元素的行为。

    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() {
    		return name;
    	}
      
    	public String getDescription() {
    		return description;
    	}
      
    	public double getPrice() {
    		return price;
    	}
      
    	public boolean isVegetarian() {
    		return vegetarian;
    	}
    
    	public Iterator<MenuComponent> createIterator() {
    		return new NullIterator();
    	}
     
    	public void print() {
    		System.out.print("  " + getName());
    		if (isVegetarian()) {
    			System.out.print("(v)");
    		}
    		System.out.println(", " + getPrice());
    		System.out.println("     -- " + getDescription());
    	}
    
    }
    

    我们已经有了菜单项,还需要组合类,这就是我们叫做菜单的。别忘了,此组合类可以持有菜单项或其他菜单。

    public class Menu extends MenuComponent {
    	Iterator<MenuComponent> iterator = null;
    	ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
    	String name;
    	String description;
      
    	public Menu(String name, String description) {
    		this.name = name;
    		this.description = description;
    	}
     
    	public void add(MenuComponent menuComponent) {
    		menuComponents.add(menuComponent);
    	}
     
    	public void remove(MenuComponent menuComponent) {
    		menuComponents.remove(menuComponent);
    	}
     
    	public MenuComponent getChild(int i) {
    		return menuComponents.get(i);
    	}
     
    	public String getName() {
    		return name;
    	}
     
    	public String getDescription() {
    		return description;
    	}
    
      
    	public Iterator<MenuComponent> createIterator() {
    		if (iterator == null) {
    			iterator = new CompositeIterator(menuComponents.iterator());
    		}
    		return iterator;
    	}
     
     
    	public void print() {
    		System.out.print("
    " + getName());
    		System.out.println(", " + getDescription());
    		System.out.println("---------------------");
    	}
    }
    

    因为菜单是一个组合,包含了菜单项和其他的菜单,所以它的print()应该打印出它所包含的一切。如果它不这么做,我们就必须遍历整个组合的每个节点,然后将每一项打印出来。这么一来,也就失去了使用组合结构的意义

    所以,print还得进行优化,如下:

    public void print() {
    	System.out.print("
    " + getName());
    	System.out.println(", " + getDescription());
    	System.out.println("---------------------");
     
    	Iterator<MenuComponent> iterator = menuComponents.iterator();
    	while (iterator.hasNext()) {
    		MenuComponent menuComponent = iterator.next();
    		menuComponent.print();
    	}
    }
    

    看到上面了没,我们用了迭代器。用它遍历所有菜单组件,遍历过程中,可能遇到其他菜单,或者是遇到菜单项。由于菜单和菜单项都实现了print,那我们只要调用print即可。

    开始测试数据之前,我们了解一下,在运行时菜单组合是什么样的:

    开始运行我们的测试程序啦:

    public class MenuTestDrive {
    	public static void main(String args[]) {
    
    		MenuComponent pancakeHouseMenu = 
    			new Menu("PANCAKE HOUSE MENU", "Breakfast");
    		MenuComponent dinerMenu = 
    			new Menu("DINER MENU", "Lunch");
    		MenuComponent cafeMenu = 
    			new Menu("CAFE MENU", "Dinner");
    		MenuComponent dessertMenu = 
    			new Menu("DESSERT MENU", "Dessert of course!");
      
    		MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined");
      
    		allMenus.add(pancakeHouseMenu);
    		allMenus.add(dinerMenu);
    		allMenus.add(cafeMenu);
      
    		pancakeHouseMenu.add(new MenuItem(
    			"K&B's Pancake Breakfast", 
    			"Pancakes with scrambled eggs, and toast", 
    			true,
    			2.99));
    		pancakeHouseMenu.add(new MenuItem(
    			"Regular Pancake Breakfast", 
    			"Pancakes with fried eggs, sausage", 
    			false,
    			2.99));
    		pancakeHouseMenu.add(new MenuItem(
    			"Blueberry Pancakes",
    			"Pancakes made with fresh blueberries, and blueberry syrup",
    			true,
    			3.49));
    		pancakeHouseMenu.add(new MenuItem(
    			"Waffles",
    			"Waffles, with your choice of blueberries or strawberries",
    			true,
    			3.59));
    
    		dinerMenu.add(new MenuItem(
    			"Vegetarian BLT",
    			"(Fakin') Bacon with lettuce & tomato on whole wheat", 
    			true, 
    			2.99));
    		dinerMenu.add(new MenuItem(
    			"BLT",
    			"Bacon with lettuce & tomato on whole wheat", 
    			false, 
    			2.99));
    		dinerMenu.add(new MenuItem(
    			"Soup of the day",
    			"A bowl of the soup of the day, with a side of potato salad", 
    			false, 
    			3.29));
    		dinerMenu.add(new MenuItem(
    			"Hotdog",
    			"A hot dog, with saurkraut, relish, onions, topped with cheese",
    			false, 
    			3.05));
    		dinerMenu.add(new MenuItem(
    			"Steamed Veggies and Brown Rice",
    			"A medly of steamed vegetables over brown rice", 
    			true, 
    			3.99));
     
    		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 icecream",
    			true,
    			1.59));
    		dessertMenu.add(new MenuItem(
    			"Cheesecake",
    			"Creamy New York cheesecake, with a chocolate graham crust",
    			true,
    			1.99));
    		dessertMenu.add(new MenuItem(
    			"Sorbet",
    			"A scoop of raspberry and a scoop of lime",
    			true,
    			1.89));
    
    		cafeMenu.add(new MenuItem(
    			"Veggie Burger and Air Fries",
    			"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
    			true, 
    			3.99));
    		cafeMenu.add(new MenuItem(
    			"Soup of the day",
    			"A cup of the soup of the day, with a side salad",
    			false, 
    			3.69));
    		cafeMenu.add(new MenuItem(
    			"Burrito",
    			"A large burrito, with whole pinto beans, salsa, guacamole",
    			true, 
    			4.29));
     
    		Waitress waitress = new Waitress(allMenus);
       
    		waitress.printVegetarianMenu();
     
    	}
    }
    

    结果这里就不附上了,请大家自行去跑代码实现吧。相信你们又对组合模式也已经有了一个大概了吧。下一篇,还有更犀利的,组合迭代器等着我们。小编马上回去搞起来,安排上。

    爱生活,爱学习,爱感悟,爱挨踢

  • 相关阅读:
    数据类型
    springboot中get post put delete 请求
    图解SQL的inner join、left join、right join、full outer join、union、union all的区别
    【转】MyBatis之级联——一对一关系
    【转】浏览器同源政策及其规避方法(2)
    【转】浏览器同源政策及其规避方法(1)
    Spring Boot配置文件详解
    【BUG】Spring Mvc使用Jackson进行json转对象时,遇到的字符串转日期的异常处理(JSON parse error: Can not deserialize value of type java.util.Date from String[])
    【转】SpringBoot Mybatis 读取配置文件
    MySQL
  • 原文地址:https://www.cnblogs.com/dimple91/p/11089204.html
Copyright © 2011-2022 走看看