• 设计模式之组合模式浅析


         
    /**
     * 
     * 
     * 组合模式: 可以使组合对象形成树形结构,以表现出整体/部分的结构,并提供一致的方法访问整体和局部
     *   组合结构内任意对象称为组件,组件可以是组合,也可以是叶节点
     * 客户可以将对象的集合以及个别的对象一视同仁
     * 
     * 运用了递归迭代的思想
     * 
     * 外部迭代器必须维护它在遍历中的位置,以便外部客户可以通过调用hasNext和next方法来驱动遍历
     * 
     * 组合和叶节点都属于组件,只是两者的角色定位不同而已
     * 组合--拥有一群子元素 
     * 叶节点--无子元素
     * 
     * @author Administrator
     * 
     */



    菜单组件

    package com.undergrowth.composition;
    
    import java.util.Iterator;
    
    /**
     * 
     * 
     * 组合模式: 可以使组合对象形成树形结构,以表现出整体/部分的结构,并提供一致的方法访问整体和局部
     *   组合结构内任意对象称为组件,组件可以是组合,也可以是叶节点
     * 客户可以将对象的集合以及个别的对象一视同仁
     * 
     * 运用了递归迭代的思想
     * 
     * 外部迭代器必须维护它在遍历中的位置,以便外部客户可以通过调用hasNext和next方法来驱动遍历
     * 
     * 组合和叶节点都属于组件,只是两者的角色定位不同而已
     * 组合--拥有一群子元素 
     * 叶节点--无子元素
     * 
     * @author Administrator
     * 
     */
    public abstract class MenuComponent {
    	/**
    	 * 提供的默认实现 让子元素决定是否重写
    	 * 
    	 * @param 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 float getPrice() {
    		throw new UnsupportedOperationException();
    	}
    
    	public String getDescription() {
    		throw new UnsupportedOperationException();
    	}
    
    	public boolean isVegetarian() {
    		throw new UnsupportedOperationException();
    	}
    
    	public void print() {
    		throw new UnsupportedOperationException();
    
    	}
    
    	public abstract Iterator createIterator();
    	
    }
    

    组合  菜单-可拥有菜单项

    package com.undergrowth.composition;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    
    public class Menu extends MenuComponent {
    
    	List<MenuComponent> menus = new ArrayList<>();
    	String name;
    	String description;
    
    	public Menu(String name, String description) {
    		super();
    		this.name = name;
    		this.description = description;
    	}
    
    	@Override
    	public void add(MenuComponent menuComponent) {
    		// TODO Auto-generated method stub
    		menus.add(menuComponent);
    	}
    
    	@Override
    	public void remove(MenuComponent menuComponent) {
    		// TODO Auto-generated method stub
    		menus.remove(menuComponent);
    	}
    
    	@Override
    	public MenuComponent getChild(int i) {
    		// TODO Auto-generated method stub
    		return menus.get(i);
    	}
    
    	@Override
    	public void print() {
    		// TODO Auto-generated method stub
    		System.out.println(getName()+","+getDescription());
    		System.out.println("===============================");
    		Iterator iteratorMenu=menus.iterator();
    		//迭代递归打印方式
    		while (iteratorMenu.hasNext()) {
    			MenuComponent menuComponent = (MenuComponent) iteratorMenu.next();
    			menuComponent.print();
    		}
    		System.out.println("==============================================================");
    		
    	}
    
    	@Override
    	public String getName() {
    		// TODO Auto-generated method stub
    		return name;
    	}
    
    	@Override
    	public String getDescription() {
    		// TODO Auto-generated method stub
    		return description;
    	}
    
    	/**
    	 * 外部迭代器 使用堆栈记录当前迭代位置
    	 */
    	@Override
    	public Iterator createIterator() {
    		// TODO Auto-generated method stub
    		return new CompositionIterator(menus.iterator());
    	}
    
    }
    

    叶子节点 菜单项

    package com.undergrowth.composition;
    
    import java.util.Iterator;
    
    public class MenuItem extends MenuComponent {
    	String name;
    	float price;
    	String description;
    	boolean vegetarian;
    	public MenuItem(String name, float price, String description,
    			boolean vegetarian) {
    		super();
    		this.name = name;
    		this.price = price;
    		this.description = description;
    		this.vegetarian = vegetarian;
    	}
    	public MenuItem(String name, String description,
    			boolean vegetarian, double price) {
    		super();
    		this.name = name;
    		this.price = (float) price;
    		this.description = description;
    		this.vegetarian = vegetarian;
    	}
    	@Override
    	public String getName() {
    		// TODO Auto-generated method stub
    		return name;
    	}
    	@Override
    	public float getPrice() {
    		// TODO Auto-generated method stub
    		return price;
    	}
    	@Override
    	public String getDescription() {
    		// TODO Auto-generated method stub
    		return description;
    	}
    	@Override
    	public boolean isVegetarian() {
    		// TODO Auto-generated method stub
    		return vegetarian;
    	}
    	@Override
    	public void print() {
    		// TODO Auto-generated method stub
    		System.out.println(toString());
    	}
    	@Override
    	public String toString() {
    		return "MenuItem [name=" + name + ", price=" + price + ", description="
    				+ description + ", vegetarian=" + vegetarian + "]";
    	}
    	@Override
    	public Iterator createIterator() {
    		// TODO Auto-generated method stub
    		return new NullIterator();
    	}
    	
    	
    	
    }
    


    组合迭代器 使用堆栈记录当前的迭代位置

    package com.undergrowth.composition;
    
    import java.util.Iterator;
    import java.util.Stack;
    
    /**
     * 外部迭代器 使用堆栈记录当前迭代的元素
     * @author Administrator
     *
     */
    public class CompositionIterator implements Iterator {
    
    	//使用堆栈 迭代树形结构
    	Stack stack=new Stack<>();
    	
    	public CompositionIterator(Iterator iterator) {
    		// TODO Auto-generated constructor stub
    		stack.push(iterator);
    	}
    
    	@Override
    	public boolean hasNext() {
    		// TODO Auto-generated method stub
    		//判断堆栈是否为空
    		if(stack.empty()){
    			return false;
    		}else {
    			Iterator iterator=(Iterator) stack.peek();
    			//判断迭代器是否遍历到最后元素
    			if(!iterator.hasNext()){
    				stack.pop();
    				return hasNext();
    			}else {
    				return true;
    			}
    		}
    		
    	}
    
    	@Override
    	public Object next() {
    		// TODO Auto-generated method stub
    		if(hasNext()){
    			Iterator iterator=(Iterator) stack.peek();
    			MenuComponent menuComponent=(MenuComponent) iterator.next();
    			//如果是菜单的话 入栈 遍历 菜单中的菜单项
    			if(menuComponent instanceof Menu)
    			{
    				stack.push(menuComponent.createIterator());
    			}
    			return menuComponent;
    		}else {
    			return null;
    		}
    		
    	}
    
    	@Override
    	public void remove() {
    		// TODO Auto-generated method stub
    		throw new UnsupportedOperationException();
    	}
    
    }
    


    空迭代器

    package com.undergrowth.composition;
    
    import java.util.Iterator;
    
    public class NullIterator implements Iterator {
    
    	@Override
    	public boolean hasNext() {
    		// TODO Auto-generated method stub
    		return false;
    	}
    
    	@Override
    	public Object next() {
    		// TODO Auto-generated method stub
    		return null;
    	}
    
    	@Override
    	public void remove() {
    		// TODO Auto-generated method stub
          throw new UnsupportedOperationException();
    	}
    
    }
    

    服务员 操作菜单

    package com.undergrowth.composition;
    
    import java.util.Iterator;
    
    public class Waitress {
    	
    	MenuComponent menuComponent;
    
    	public Waitress(MenuComponent menuComponent) {
    		super();
    		this.menuComponent = menuComponent;
    	}
    	
    	public void print(){
    		menuComponent.print();
    	}
    	
    	/**
    	 * 打印菜单中的素菜菜单项
    	 */
    	public void printVegetarianName(){
    		Iterator iteratorAll=menuComponent.createIterator();
    		while (iteratorAll.hasNext()) {
    			MenuComponent currMenuComponent = (MenuComponent) iteratorAll.next();
    			try { 
    				//表示是菜单项 并且是素菜
    				if(currMenuComponent.isVegetarian()){
    					System.out.println(currMenuComponent);
    				}
    			} catch (Exception e) {
    				// TODO: handle exception
    				//菜单 会抛出异常
    			}
    		}
    	}
    	
    }
    

    测试

    package com.undergrowth.composition.test;
    
    import static org.junit.Assert.*;
    
    import org.junit.Test;
    
    import com.undergrowth.composition.Menu;
    import com.undergrowth.composition.MenuComponent;
    import com.undergrowth.composition.MenuItem;
    import com.undergrowth.composition.Waitress;
    
    public class MenuComponentTest {
    
    	@Test
    	public void test() {
    		//构建菜单树
    		MenuComponent coffeeMenuComponent=new Menu("咖啡菜单", "各种口味的咖啡");
    		MenuComponent dessert=new Menu("甜点菜单", "喝咖啡的时候,还可以来点甜点");
    		MenuComponent beverage=new Menu("饮料菜单", "品尝甜点的时候,再来点饮料");
    		beverage.add(new MenuItem("柠檬雪碧", 22, "加冰,口感更好", true));
    		dessert.add(new MenuItem("酸奶蜂蜜冰淇淋", 57, "口感新颖独特,视觉效果也是一流", true));
    		dessert.add(new MenuItem("小粉猪奶黄包", 37, "憨态可掬的小粉猪奶黄包", true));
    		dessert.add(beverage);
    		coffeeMenuComponent.add(dessert);
    		coffeeMenuComponent.add(new MenuItem("拿铁咖啡", 100, "咖啡与牛奶的交融", true));
    		coffeeMenuComponent.add(new MenuItem("越南咖啡", 200, "采用纯正的越南咖啡豆", true));
    		coffeeMenuComponent.add(new MenuItem("美式咖啡", 80, "清新的风味中不失本香", true));
    		
    		MenuComponent chineseMenuComponent=new Menu("中国菜菜单", "美味的中国菜");
    		chineseMenuComponent.add(new MenuItem("宫保鸡", 45, "宫保鸡丁是川菜的代表菜,由鸡脯肉、干辣椒、花生米炒制而成,香辣好吃", false));
    		chineseMenuComponent.add(new MenuItem("糖醋里脊", 78, "糖醋里脊色泽红亮、酸甜可口、外酥里嫩", false));
    		chineseMenuComponent.add(new MenuItem("烤鸭", 80, "北京烤鸭,被誉为“天下美味”而驰名中外,它更以色泽红润,肉质细嫩,味道醇厚,肥而不腻的特色而享誉海内外", false));
    		
    		MenuComponent allmenus=new Menu("根菜单", "所有菜单的入口");
    		allmenus.add(coffeeMenuComponent);
    		allmenus.add(chineseMenuComponent);
    		
    		Waitress waitress=new Waitress(allmenus);
    		waitress.print();
    		System.out.println("
    
    
    ");
    		System.out.println("==========================打印素食====================================");
    		waitress.printVegetarianName();
    		
    	}
    
    }
    


    控制台输出

    根菜单,所有菜单的入口
    ===============================
    咖啡菜单,各种口味的咖啡
    ===============================
    甜点菜单,喝咖啡的时候,还可以来点甜点
    ===============================
    MenuItem [name=酸奶蜂蜜冰淇淋, price=57.0, description=口感新颖独特,视觉效果也是一流, vegetarian=true]
    MenuItem [name=小粉猪奶黄包, price=37.0, description=憨态可掬的小粉猪奶黄包, vegetarian=true]
    饮料菜单,品尝甜点的时候,再来点饮料
    ===============================
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    ==============================================================
    ==============================================================
    MenuItem [name=拿铁咖啡, price=100.0, description=咖啡与牛奶的交融, vegetarian=true]
    MenuItem [name=越南咖啡, price=200.0, description=采用纯正的越南咖啡豆, vegetarian=true]
    MenuItem [name=美式咖啡, price=80.0, description=清新的风味中不失本香, vegetarian=true]
    ==============================================================
    中国菜菜单,美味的中国菜
    ===============================
    MenuItem [name=宫保鸡, price=45.0, description=宫保鸡丁是川菜的代表菜,由鸡脯肉、干辣椒、花生米炒制而成,香辣好吃, vegetarian=false]
    MenuItem [name=糖醋里脊, price=78.0, description=糖醋里脊色泽红亮、酸甜可口、外酥里嫩, vegetarian=false]
    MenuItem [name=烤鸭, price=80.0, description=北京烤鸭,被誉为“天下美味”而驰名中外,它更以色泽红润,肉质细嫩,味道醇厚,肥而不腻的特色而享誉海内外, vegetarian=false]
    ==============================================================
    ==============================================================
    
    
    
    
    ==========================打印素食====================================
    MenuItem [name=酸奶蜂蜜冰淇淋, price=57.0, description=口感新颖独特,视觉效果也是一流, vegetarian=true]
    MenuItem [name=小粉猪奶黄包, price=37.0, description=憨态可掬的小粉猪奶黄包, vegetarian=true]
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    MenuItem [name=酸奶蜂蜜冰淇淋, price=57.0, description=口感新颖独特,视觉效果也是一流, vegetarian=true]
    MenuItem [name=小粉猪奶黄包, price=37.0, description=憨态可掬的小粉猪奶黄包, vegetarian=true]
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    MenuItem [name=柠檬雪碧, price=22.0, description=加冰,口感更好, vegetarian=true]
    MenuItem [name=拿铁咖啡, price=100.0, description=咖啡与牛奶的交融, vegetarian=true]
    MenuItem [name=越南咖啡, price=200.0, description=采用纯正的越南咖啡豆, vegetarian=true]
    MenuItem [name=美式咖啡, price=80.0, description=清新的风味中不失本香, vegetarian=true]
    




      其实   在打印素食菜单项的时候  会发现有些菜单项 重复打印了 这是因为采用堆栈进行处理时  会产生多级入栈与出栈 导致的 自己动手画画啊  或者调试一下 就清楚了

  • 相关阅读:
    [Intellij] 软件设置和常用快捷键
    [Intellij] Project Structure 配置说明
    [日志log] 常用log日志记录方式对比和详解
    [J2EE]web.xml各个版本模板
    [技术选型] CDH-Cloudera Distribution Hadoop
    [技术选型] dubbo
    [技术选型] spring boot
    [hbase] HBase内置过滤器的一些总结
    [zookeeper] Zookeeper伪分布式集群配置
    [maven] settings 文件 本地maven仓库
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275538.html
Copyright © 2020-2023  润新知