zoukankan      html  css  js  c++  java
  • 设计模式学习--迭代器模式(Iterator Pattern)和组合模式(Composite Pattern)

    设计模式学习--迭代器模式(Iterator Pattern)

    概述

    ———————————————————————————————————————————————————

    迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示

    把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。


    组合模式允许你将对象组成树形结构来表现“整体/部分”的层次结构。组合能让客户以一致的方式处理个别对象和对象组合。

    OO原则

    ———————————————————————————————————————————————————

    • 封装变化
    • 多用组合,少用继承
    • 针对接口编程,不针对实现编程
    • 为交互对象之间的松耦合设计而努力
    • 类应该对扩展开放,对修改关闭
    • 依赖抽象,不要依赖具体类
    • 只和朋友交谈
    • 别找我,我会找你
    • 类应该只有一个改变的理由


    要点

    ———————————————————————————————————————————————————

    • 迭代器允许访问聚合的元素,而不需要暴露它的内部结构
    • 迭代器将遍历聚合的工作封装进一个对象中。
    • 当使用迭代器的时候,我们依赖聚合提供遍历。
    • 迭代器提供一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。
    • 我们应该努力让一个类分配一个责任。
    • 组合模式提供一个结构,可同时包容个别对象和组合对象。
    • 组合模式允许客户对个别对象以及组合对象一视同仁。
    • 组合结构内的任意对象成为组件,组件可以是组合,也可以是叶节点。
    • 在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。

    例子1

    ———————————————————————————————————————————————————

    自定义迭代器

    Iterator

    package dinermerger;
    
    /**
     * 自定义迭代器接口
     * @author wwj
     *
     */
    public interface Iterator {
    	boolean hasNext();		//是否还有下一个元素
    	Object next();			//返回下一个元素
    }
    


    实现迭代器

    DinerMenuIterator

    package dinermerger;
    
    /**
     * 实现一个具体的迭代器,为餐厅菜单服务
     * @author Administrator
     *
     */
    public class DinerMenuIterator implements Iterator {
    	MenuItem[] items;
    	int position = 0;	//记录当前数组遍历的位置
    	
    	public DinerMenuIterator(MenuItem[] items) {
    		this.items = items;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(position >= items.length || items[position] == null) {
    			return false;
    		} else {
    			return true;
    		}
    	}
    
    	@Override
    	public Object next() {
    		MenuItem menuItem = items[position];
    		position = position + 1;
    		return menuItem;
    	}
    
    }


    PancakeHouseMenuIterator

    package dinermerger;
    
    import java.util.ArrayList;
    
    /**
     * 煎饼屋菜单实现
     * @author wwj
     *
     */
    public class PancakeHouseMenuIterator implements Iterator{
    	ArrayList menuItems;
    	int position = 0;
    	
    	public PancakeHouseMenuIterator(ArrayList menuItems) {
    		this.menuItems = menuItems;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(position >= menuItems.size()) {
    			return false;
    		} else {
    			return true;
    		}
    	}
    
    	@Override
    	public Object next() {
    		Object object = menuItems.get(position);
    		position = position + 1;
    		return object;
    	}
    }
    


    菜单项

    package dinermerger;
    
    /**
     * 菜单项
     * @author wwj
     *
     */
    public class MenuItem {
    	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;
    	}
    	
    	
    	
    }
    


    菜单

    PancakeHouseMenu

    package dinermerger;
    
    import java.util.ArrayList;
    
    /**
     * 煎饼屋菜单实现
     * @author wwj
     *
     */
    public class PancakeHouseMenu {
    	ArrayList menuItems;
    	public PancakeHouseMenu() {
    		menuItems = new ArrayList();
    		
    		addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
    		
    		addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
    		
    		addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
    		
    		addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
    		
    	}
    	
    	/**
    	 * 创建一个新的菜单项对象,传入每一个变量,然后将它加入到ArrayList中
    	 * @param name	菜名
    	 * @param description 叙述
    	 * @param vegetarian  是否为素食
    	 * @param price	价格
    	 */
    	public void addItem(String name, String description, boolean vegetarian, double price) {
    		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    		menuItems.add(menuItem);
    	}
    	
    /*	public ArrayList getMenuItems() {
    		return menuItems;
    	}*/
    	
    	
    	public Iterator createIterator() {
    		return new PancakeHouseMenuIterator(menuItems);
    	}
    }
    



    DinerMenu

    package dinermerger;
    
    /**
     * 餐厅菜单
     * @author wwj
     *
     */
    public class DinerMenu {
    	static final int MAX_ITEMS = 6;
    	int numberOfItems = 0;
    	MenuItem[] menuItems;		//使用一个数组,所以可以控制菜单的长度,并且在取出菜单项的时候,不需要转型
    	
    	
    	public DinerMenu() {
    		menuItems = new MenuItem[MAX_ITEMS];
    		addItem("Vegetarian BLT",
    				"(Fakin') Bacon with lettuce & tomato on Whole wheat", true,
    				2.99);
    
    		addItem("BLT", "Bacon with lettuce & tomato on Whole wheat", false,
    				2.99);
    
    		addItem("Soup of the day",
    				"Soup of the day, with a side of potato salad", false, 3.29);
    
    		addItem("Hotdog",
    				"A hot dog, with saurkraut, relish, onions, topped with cheese",
    				false, 3.05);
    
    		addItem("Steamed Veggies and Brown Rice",
    				"Steamed vegetables over brown rice", true, 3.99);
    		addItem("Pasta",
    				"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
    				true, 3.89);
    	}
    
    
    	
    	private void addItem(String name, String description, boolean vegetarian, double price) {
    		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    		if(numberOfItems >= MAX_ITEMS) {
    			System.err.println("Sorry, menu is full! Can't add item to menu");
    		} else {
    			menuItems[numberOfItems] = menuItem;
    			numberOfItems = numberOfItems + 1;
    		}
    	}
    	
    	
    	
    	/**
    	 * 增加了迭代器之后,这个方法就不需要了
    	 * @return
    	 */
    	/*public MenuItem[] getMenuItems() {
    		return menuItems;
    	}*/
    	
    	
    	/**
    	 * 用来从菜单项数组创建一个DinerMenuIterator,并将它返回给客户
    	 */
    	public Iterator createIterator() {
    		return new DinerMenuIterator(menuItems);
    	}
    	
    }
    


    女招待

    package dinermerger;
    
    /**
     * 女招待类
     * @author wwj
     *
     */
    public class Waitress {
    	PancakeHouseMenu pancakeHouseMenu;
    	DinerMenu dinerMenu;
    	
    	/**
    	 *在这个构造器中,女招待照顾两个菜单
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 */
    	public Waitress(PancakeHouseMenu pancakeHouseMenu, DinerMenu dinerMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    	}
    	
    	public void printMenu() {
    		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
    		Iterator dinerIterator = dinerMenu.createIterator();
    		System.out.println("MENU
    ----
    BREAKFAST");
    		printMenu(pancakeIterator);
    		System.out.println("
    LUNCH");
    		printMenu(dinerIterator);
    	}
    
    	private void printMenu(Iterator iterator) {
    		while(iterator.hasNext()) {	//测试是否还有其他项
    			MenuItem menuItem = (MenuItem) iterator.next();
    			System.out.print(menuItem.getName() + ", ");
    			System.out.print(menuItem.getPrice() + " -- ");
    			System.out.println(menuItem.getDescription());
    		}
    	}
    }
    


    测试

    package dinermerger;
    
    public class MenuTestDrive {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    		DinerMenu dinerMenu = new DinerMenu();
    		
    		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
    		
    		waitress.printMenu();
    	}
    
    }
    


    结果:

    MENU
    ----
    BREAKFAST
    K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
    Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
    Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries
    Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries


    LUNCH
    Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on Whole wheat
    BLT, 2.99 -- Bacon with lettuce & tomato on Whole wheat
    Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
    Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
    Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
    Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread



    例子2

    ———————————————————————————————————————————————————

    利用java.util.Iterator来实现迭代器

    提供一个Menu接口,让PancakeHouseMenu和DinerMenu都实现Menu接口,这样Waitress就不用依赖具体的菜单的问题,也不用依赖菜单项的具体实现了。


    package dinermerger;
    
    /**
     * 这是一个简单的接口,让客户能够取得菜单项
     * @author Administrator
     *
     */
    public interface Menu {
    	public Iterator createIterator();
    }
    


    DinerMenu

    package dinermerger;
    
    import java.util.Iterator;
    
    /**
     * 餐厅菜单
     * @author wwj
     *
     */
    public class DinerMenu implements Menu{
    	static final int MAX_ITEMS = 6;
    	int numberOfItems = 0;
    	MenuItem[] menuItems;		//使用一个数组,所以可以控制菜单的长度,并且在取出菜单项的时候,不需要转型
    	
    	
    	public DinerMenu() {
    		menuItems = new MenuItem[MAX_ITEMS];
    		addItem("Vegetarian BLT",
    				"(Fakin') Bacon with lettuce & tomato on Whole wheat", true,
    				2.99);
    
    		addItem("BLT", "Bacon with lettuce & tomato on Whole wheat", false,
    				2.99);
    
    		addItem("Soup of the day",
    				"Soup of the day, with a side of potato salad", false, 3.29);
    
    		addItem("Hotdog",
    				"A hot dog, with saurkraut, relish, onions, topped with cheese",
    				false, 3.05);
    
    		addItem("Steamed Veggies and Brown Rice",
    				"Steamed vegetables over brown rice", true, 3.99);
    		addItem("Pasta",
    				"Spaghetti with Marinara Sauce, and a slice of sourdough bread",
    				true, 3.89);
    	}
    
    
    	
    	private void addItem(String name, String description, boolean vegetarian, double price) {
    		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    		if(numberOfItems >= MAX_ITEMS) {
    			System.err.println("Sorry, menu is full! Can't add item to menu");
    		} else {
    			menuItems[numberOfItems] = menuItem;
    			numberOfItems = numberOfItems + 1;
    		}
    	}
    	
    	
    	
    	/**
    	 * 增加了迭代器之后,这个方法就不需要了
    	 * @return
    	 */
    	/*public MenuItem[] getMenuItems() {
    		return menuItems;
    	}*/
    	
    	
    	/**
    	 * 用来从菜单项数组创建一个DinerMenuIterator,并将它返回给客户
    	 */
    	public Iterator createIterator() {
    		return new DinerMenuIterator(menuItems);
    	}
    	
    }
    


    PancakeHouseMenu

    不创建自己的迭代器,而是调用ArrayList的iterator()方法

    package dinermerger;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    /**
     * 煎饼屋菜单实现
     * @author wwj
     *
     */
    public class PancakeHouseMenu implements Menu{
    	ArrayList menuItems;
    	public PancakeHouseMenu() {
    		menuItems = new ArrayList();
    		
    		addItem("K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99);
    		
    		addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99);
    		
    		addItem("Blueberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49);
    		
    		addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59);
    		
    	}
    	
    	/**
    	 * 创建一个新的菜单项对象,传入每一个变量,然后将它加入到ArrayList中
    	 * @param name	菜名
    	 * @param description 叙述
    	 * @param vegetarian  是否为素食
    	 * @param price	价格
    	 */
    	public void addItem(String name, String description, boolean vegetarian, double price) {
    		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    		menuItems.add(menuItem);
    	}
    	
    /*	public ArrayList getMenuItems() {
    		return menuItems;
    	}*/
    	
    	
    	public Iterator createIterator() {
    		return menuItems.iterator();
    	}
    }
    


    DinerMenuIterator

    package dinermerger;
    
    import java.util.Iterator;
    
    /**
     * 实现一个具体的迭代器,为餐厅菜单服务
     * @author Administrator
     *
     */
    public class DinerMenuIterator implements Iterator {
    	MenuItem[] items;
    	int position = 0;	//记录当前数组遍历的位置
    	
    	public DinerMenuIterator(MenuItem[] items) {
    		this.items = items;
    	}
    
    	@Override
    	public boolean hasNext() {
    		if(position >= items.length || items[position] == null) {
    			return false;
    		} else {
    			return true;
    		}
    	}
    
    	@Override
    	public Object next() {
    		MenuItem menuItem = items[position];
    		position = position + 1;
    		return menuItem;
    	}
    
    	@Override
    	public void remove() {
    		if(position <= 0) {
    			throw new IllegalStateException("You can't remove an item until you've done at least on next()");
    		}
    		if(items[position - 1] != null) {
    			for(int i = position - 1; i < (items.length - 1); i++) {
    				items[i] = items[i + 1];
    			}
    			items[items.length - 1] = null;
    		}
    		
    	}
    
    }
    


    Waitress

    package dinermerger;
    
    import java.util.Iterator; 
    
    /**
     * 女招待类
     * @author wwj
     *
     */
    public class Waitress {
    //	PancakeHouseMenu pancakeHouseMenu;
    //	DinerMenu dinerMenu;
    	Menu pancakeHouseMenu;
    	Menu dinerMenu;
    	
    	/**
    	 *在这个构造器中,女招待照顾两个菜单
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 */
    	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    	}
    	
    	public void printMenu() {
    		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
    		Iterator dinerIterator = dinerMenu.createIterator();
    		System.out.println("MENU
    ----
    BREAKFAST");
    		printMenu(pancakeIterator);
    		System.out.println("
    LUNCH");
    		printMenu(dinerIterator);
    	}
    
    	private void printMenu(Iterator iterator) {
    		while(iterator.hasNext()) {	//测试是否还有其他项
    			MenuItem menuItem = (MenuItem) iterator.next();
    			System.out.print(menuItem.getName() + ", ");
    			System.out.print(menuItem.getPrice() + " -- ");
    			System.out.println(menuItem.getDescription());
    		}
    	}
    }
    


    增加一个CafeMenu会变成以下这样

    package dinermerger;
    
    import java.util.Hashtable;
    import java.util.Iterator;
    
    /**
     * 咖啡厅菜单
     * @author wwj
     *
     */
    public class CafeMenu implements Menu{
    	Hashtable menuItems = new Hashtable();
    	
    	public CafeMenu() {
    		addItem("Veggie Burger and Air Fries",
    				"Veggie burger on a whole wheat bun, lettuce, tomato, and fries",
    				true, 3.99);
    		addItem("Soup of the day",
    				"A cup of the soup of the day, with a side salad", false, 3.69);
    		addItem("Burrito",
    				"A large burrito, with whole pinto beans, salsa, guacamole",
    				true, 4.29);
    	}
    	
    	
    	public void addItem(String name, String description, boolean vegetarian, double price) {
    		MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
    		menuItems.put(menuItem.getName(), menuItem);
    	}
    
    
    	@Override
    	public Iterator createIterator() {
    		return menuItems.values().iterator();
    	}
    }
    


    package dinermerger;
    
    import java.util.Iterator; 
    
    /**
     * 女招待类
     * @author wwj
     *
     */
    public class Waitress {
    //	PancakeHouseMenu pancakeHouseMenu;
    //	DinerMenu dinerMenu;
    	Menu pancakeHouseMenu;
    	Menu dinerMenu;
    	Menu cafeMenu;	
    	
    	/**
    	 *在这个构造器中,女招待照顾两个菜单
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 */
    	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    	}
    	
    	/**
    	 * 新增一个cafeMenu
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 * @param cafeMenu
    	 */
    	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    		this.cafeMenu = cafeMenu;
    	}
    
    
    
    	public void printMenu() {
    		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
    		Iterator dinerIterator = dinerMenu.createIterator();
    		Iterator cafeIterator = cafeMenu.createIterator();
    		System.out.println("MENU
    ----
    BREAKFAST");
    		printMenu(pancakeIterator);
    		System.out.println("
    LUNCH");
    		printMenu(dinerIterator);
    		System.out.println("
    DINNER");
    		printMenu(cafeIterator);
    	}
    
    	private void printMenu(Iterator iterator) {
    		while(iterator.hasNext()) {	//测试是否还有其他项
    			MenuItem menuItem = (MenuItem) iterator.next();
    			System.out.print(menuItem.getName() + ", ");
    			System.out.print(menuItem.getPrice() + " -- ");
    			System.out.println(menuItem.getDescription());
    		}
    	}
    }
    


    Test

    package dinermerger;
    
    public class MenuTestDrive {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    //		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    //		DinerMenu dinerMenu = new DinerMenu();
    //		
    //		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
    //		
    //		waitress.printMenu();
    		
    		Menu pancakeHouseMenu = new PancakeHouseMenu();
    		Menu dinerMenu = new DinerMenu();
    		Menu cafeMenu = new CafeMenu();
    		
    		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu);
    		waitress.printMenu();
    	}
    
    }
    


    结果:

    MENU
    ----
    BREAKFAST
    K&B's Pancake Breakfast, 2.99 -- Pancakes with scrambled eggs, and toast
    Regular Pancake Breakfast, 2.99 -- Pancakes with fried eggs, sausage
    Blueberry Pancakes, 3.49 -- Pancakes made with fresh blueberries
    Waffles, 3.59 -- Waffles, with your choice of blueberries or strawberries


    LUNCH
    Vegetarian BLT, 2.99 -- (Fakin') Bacon with lettuce & tomato on Whole wheat
    BLT, 2.99 -- Bacon with lettuce & tomato on Whole wheat
    Soup of the day, 3.29 -- Soup of the day, with a side of potato salad
    Hotdog, 3.05 -- A hot dog, with saurkraut, relish, onions, topped with cheese
    Steamed Veggies and Brown Rice, 3.99 -- Steamed vegetables over brown rice
    Pasta, 3.89 -- Spaghetti with Marinara Sauce, and a slice of sourdough bread


    DINNER
    Soup of the day, 3.69 -- A cup of the soup of the day, with a side salad
    Burrito, 4.29 -- A large burrito, with whole pinto beans, salsa, guacamole
    Veggie Burger and Air Fries, 3.99 -- Veggie burger on a whole wheat bun, lettuce, tomato, and fries


    为了让女招待更加有扩展性,我们这样做

    package dinermerger;
    
    import java.util.ArrayList;
    import java.util.Iterator; 
    
    /**
     * 女招待类
     * @author wwj
     *
     */
    public class Waitress {
    //	PancakeHouseMenu pancakeHouseMenu;
    //	DinerMenu dinerMenu;
    //	Menu pancakeHouseMenu;
    //	Menu dinerMenu;
    //	Menu cafeMenu;	
    	ArrayList menus;
    	
    /*	*//**
    	 *在这个构造器中,女招待照顾两个菜单
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 *//*
    	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    	}
    	
    	*//**
    	 * 新增一个cafeMenu
    	 * @param pancakeHouseMenu
    	 * @param dinerMenu
    	 * @param cafeMenu
    	 *//*
    	public Waitress(Menu pancakeHouseMenu, Menu dinerMenu, Menu cafeMenu) {
    		this.pancakeHouseMenu = pancakeHouseMenu;
    		this.dinerMenu = dinerMenu;
    		this.cafeMenu = cafeMenu;
    	}*/
    
    	public Waitress(ArrayList menus) {
    		this.menus = menus;
    	}
    
    
    
    	public void printMenu() {
    /*		Iterator pancakeIterator = pancakeHouseMenu.createIterator();
    		Iterator dinerIterator = dinerMenu.createIterator();
    		Iterator cafeIterator = cafeMenu.createIterator();
    		System.out.println("MENU
    ----
    BREAKFAST");
    		printMenu(pancakeIterator);
    		System.out.println("
    LUNCH");
    		printMenu(dinerIterator);
    		System.out.println("
    DINNER");
    		printMenu(cafeIterator);*/
    		Iterator menuIterator = menus.iterator();
    		while(menuIterator.hasNext()) {
    			Menu menu = (Menu)menuIterator.next();
    			printMenu(menu.createIterator());
    		}
    		
    	}
    
    	
    	private void printMenu(Iterator iterator) {
    		while(iterator.hasNext()) {	//测试是否还有其他项
    			MenuItem menuItem = (MenuItem) iterator.next();
    			System.out.print(menuItem.getName() + ", ");
    			System.out.print(menuItem.getPrice() + " -- ");
    			System.out.println(menuItem.getDescription());
    		}
    	}
    }
    


    测试的时候我们就可以这样

    package dinermerger;
    
    import java.util.ArrayList;
    
    public class MenuTestDrive {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) {
    //		PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
    //		DinerMenu dinerMenu = new DinerMenu();
    //		
    //		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu);
    //		
    //		waitress.printMenu();
    		
    		Menu pancakeHouseMenu = new PancakeHouseMenu();
    		Menu dinerMenu = new DinerMenu();
    		Menu cafeMenu = new CafeMenu();
    		
    //		Waitress waitress = new Waitress(pancakeHouseMenu, dinerMenu, cafeMenu);
    		ArrayList menus = new ArrayList();
    		menus.add(pancakeHouseMenu);
    		menus.add(dinerMenu);
    		menus.add(cafeMenu);
    		Waitress waitress = new Waitress(menus);
    		waitress.printMenu();
    	}
    
    }
    


    总算是要讲到组合模式了,这个模式可以解决迭代器模式中不能解决的一个难题。比如我们需要一个新的餐单,菜单下又有子菜单,单单用迭代器就不能解决了。这时候可以考虑到用树形结构来展示整个菜单。

    看下面的例子吧:

    定义菜单组件

    package composite;
    
    /**
     * 定义菜单组件
     * @author Administrator
     *
     */
    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 void print() {
    		throw new UnsupportedOperationException();
    	}
    }
    


    实现菜单

    package composite;
    
    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) {
    		menuComponents.add(menuComponent);
    	}
    	
    	public void remove(MenuComponent menuComponent) {
    		menuComponents.remove(menuComponent);
    	}
    	
    	public MenuComponent getChild(int i) {
    		return (MenuComponent) menuComponents.get(i);
    	}
    
    
    	public String getName() {
    		return name;
    	}
    
    
    	public String getDescription() {
    		return description;
    	}
    	
    	
    	public void print(){
    		System.out.print("
    " + getName());
    		System.out.println(", " + getDescription());
    		System.out.println("------------------");
    		
    		Iterator iterator = menuComponents.iterator();
    		while(iterator.hasNext()) {
    			MenuComponent menuComponent =
    				(MenuComponent) iterator.next();
    			menuComponent.print();
    		}
    	}
    }
    


    实现菜单项

    package composite;
    
    /**
     * 实现菜单项
     * @author Administrator
     *
     */
    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 boolean isVegetarian() {
    		return vegetarian;
    	}
    
    	public double getPrice() {
    		return price;
    	}
    	
    	
    	public void print(){
    		System.out.print("  " + getName());
    		if(isVegetarian()) {
    			System.out.print("(v)");
    		}
    		System.out.println("," + getPrice());
    		System.out.println("    --" + getDescription());
    	}
    	
    	
    }
    


    变得十分快乐的女招待

    package composite;
    
    import java.util.Iterator;
      
    public class Waitress {
    	MenuComponent allMenus;
     
    	public Waitress(MenuComponent allMenus) {
    		this.allMenus = allMenus;
    	}
     
    	public void printMenu() {
    		allMenus.print();
    	}
    }
    


    我们这样测试

    package composite;
    
    import java.util.*;
    
    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 coffeeMenu = new Menu("COFFEE MENU", "Stuff to go with your afternoon coffee");
      
    		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",
    			"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));
    
    		cafeMenu.add(coffeeMenu);
    
    		coffeeMenu.add(new MenuItem(
    			"Coffee Cake",
    			"Crumbly cake topped with cinnamon and walnuts",
    			true,
    			1.59));
    		coffeeMenu.add(new MenuItem(
    			"Bagel",
    			"Flavors include sesame, poppyseed, cinnamon raisin, pumpkin",
    			false,
    			0.69));
    		coffeeMenu.add(new MenuItem(
    			"Biscotti",
    			"Three almond or hazelnut biscotti cookies",
    			true,
    			0.89));
     
    		Waitress waitress = new Waitress(allMenus);
       
    		waitress.printMenu();
    	}
    }
    


    测试结果:



    ALL MENUS, All menus combined
    ------------------


    PANCAKE HOUSE MENU, Breakfast
    ------------------
      K&B's Pancake Breakfast(v),2.99
        --Pancakes with scrambled eggs, and toast
      Regular Pancake Breakfast,2.99
        --Pancakes with fried eggs, sausage
      Blueberry Pancakes(v),3.49
        --Pancakes made with fresh blueberries, and blueberry syrup
      Waffles(v),3.59
        --Waffles, with your choice of blueberries or strawberries


    DINER MENU, Lunch
    ------------------
      Vegetarian BLT(v),2.99
        --(Fakin') Bacon with lettuce & tomato on whole wheat
      BLT,2.99
        --Bacon with lettuce & tomato on whole wheat
      Soup of the day,3.29
        --A bowl of the soup of the day, with a side of potato salad
      Hotdog,3.05
        --A hot dog, with saurkraut, relish, onions, topped with cheese
      Steamed Veggies and Brown Rice(v),3.99
        --Steamed vegetables over brown rice
      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 icecream
      Cheesecake(v),1.99
        --Creamy New York cheesecake, with a chocolate graham crust
      Sorbet(v),1.89
        --A scoop of raspberry and a scoop of lime


    CAFE MENU, Dinner
    ------------------
      Veggie Burger and Air Fries(v),3.99
        --Veggie burger on a whole wheat bun, lettuce, tomato, and fries
      Soup of the day,3.69
        --A cup of the soup of the day, with a side salad
      Burrito(v),4.29
        --A large burrito, with whole pinto beans, salsa, guacamole


    COFFEE MENU, Stuff to go with your afternoon coffee
    ------------------
      Coffee Cake(v),1.59
        --Crumbly cake topped with cinnamon and walnuts
      Bagel,0.69
        --Flavors include sesame, poppyseed, cinnamon raisin, pumpkin
      Biscotti(v),0.89
        --Three almond or hazelnut biscotti cookies

  • 相关阅读:
    Django的model form
    Django之验证码
    ajax获取跨域数据
    js+css模仿打字效果
    CSS自定义消息提示
    CSS画各种二维图形
    最简单的动态进度条
    利用javascript(自定义事件)记录尺寸可变元素的尺寸变化过程
    超级简单的利用javascript实现文件拖拽事件
    javascript 公历与农历相互转换工具类
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3177778.html
Copyright © 2011-2022 走看看