zoukankan      html  css  js  c++  java
  • 设计模式之组合模式

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

      以菜单为例思考,这个模式可以创建一个树形结构,在同一个结构中处理嵌套菜单和菜单项组,菜单包含子菜单,子菜单下分为菜单项,任何一个菜单都是一种组合,它既可以包含其他菜单,也可以包含菜单项。

     

      菜单类和菜单项类继承同一个父类,继承的方法不同,但是我们可以忽略个别对象和对象组合的区别。

      组合模式的类图如下:

     

     下面我们结合迭代器模式和组合模式,实现遍历打印菜单,具体类图如下:

       

     MenuComponent类

     

    import java.util.Iterator;
    /**
       菜单组件类,菜单项和菜单都要继承的父类。
    **/
    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 getPrice()
        {
            throw new UnsupportedOperationException();
        }
        public void print()
        {
            throw new UnsupportedOperationException();
        }
        public Iterator createIterator()
        {
            throw new UnsupportedOperationException();
        }
        
    }
      
    

      

    继承了MenuComponent类的Menu类

     

    /**
    菜单组件类,菜单项和菜单都要继承的父类。
    **/
    public class Menu extends MenuComponent
    {
        ArrayList<MenuComponent> menuComponents;
        String name;
        public Menu(String name)
        {
            this.name=name;
            menuComponents=new ArrayList<MenuComponent>();
        }
        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 void print()
        {
            System.out.println("Menu:"+name);
            System.out.println("-----------------");
            Iterator iterator=createIterator();
            while(iterator.hasNext())
            {
                MenuComponent menuComponent=(MenuComponent)iterator.next();
                menuComponent.print();
    
            }
        }
        public Iterator createIterator()
        {
            return new CompositeIterator(menuComponents.iterator());
        }
    
    }                                        
    

      

     继承了MenuComponent类的MenuItem类,相当于菜单项

     

    import java.util.Iterator;
    /**
       菜单项类,继承了菜单组件类
    **/
    public  class MenuItem extends MenuComponent
    {
    	String name;
    	String price;
    	public MenuItem(String name,String price)
    	{
    		this.name=name;
    		this.price=price;	
    	}
    	
    	public String getName()
    	{
    		return name;
    	}
    	public String getPrice()
    	{
    		return price;
    	}
    	public void print()
    	{
    		System.out.println(name+":"+price);
    	}
    	public Iterator createIterator()
    	{
    		return new NullIterator();
    	}
    	
    }
    

      CompositeIterator类,作为菜单的迭代器

    import java.util.*;
    public class CompositeIterator implements Iterator
    {
        Stack stack;
        public CompositeIterator(Iterator iterator)
        {
            stack=new Stack();
            stack.push(iterator);
        } 
        public Object next()
        {
            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;
        }
        public boolean hasNext()
        {
            if(stack.isEmpty())
            {
                return false;
            }
            else
            {
                Iterator iterator=(Iterator)stack.peek();
                if(!iterator.hasNext())
                {
                    stack.pop();
                    return hasNext();    
                }
                else
                {
                    return true;
                }
    
            }
        }
        public void remove()
        {
            throw new UnsupportedOperationException();
        }
    
    
    
    
    } 

     NullIterator类,作为菜单项的迭代器

    import java.util.Iterator;
    public class NullIterator implements Iterator
    {
    	public Object next()
    	{
    		return null;
    	}
    	public boolean hasNext()
    	{
    		return false;
    	}
    	public void remove()
    	{
    		throw new UnsupportedOperationException();
    	}
    
    
    
    
    }
    

       Waitress类,大大降低了Waitress类与菜单之间的耦合度,Waitress类只需要知道根节点就可以了。

      

    import java.util.Iterator;
    /**
    Client
    **/
    public class Waitress
    {
        MenuComponent menus;
        public Waitress(MenuComponent menuComponent)
        {
            this.menus=menuComponent;
        }
        public void printMenu()
        {
            menus.print();
        
        }
    }
    

      

       测试类

       

    package com.qingfei.composite;
    public class Test
    {
    	public static void main(String[] args)
    	{
    		MenuComponent menus=new Menu("all Menu");
    		MenuComponent dinerMenu=new Menu("Diner Menu");
    		MenuComponent pancakeMenu=new Menu("Pancake Menu");
    		MenuComponent cafeMenu=new Menu("cafe Menu");
    		menus.add(dinerMenu);
    		menus.add(pancakeMenu);
    		dinerMenu.add(new MenuItem("noodle","10"));
    		dinerMenu.add(new MenuItem("rice","20"));
    		dinerMenu.add(new MenuItem("soup","5"));
    		cafeMenu.add(new MenuItem("latte","30"));
    		cafeMenu.add(new MenuItem("mocha","25"));	
    		pancakeMenu.add(new MenuItem("pizza","50"));
    		pancakeMenu.add(new MenuItem("cheese burger","20"));
    		pancakeMenu.add(cafeMenu);
    		Waitress service=new Waitress(menus);
    		service.printMenu();
    
    	}
    
    
    }
    

        结果是

        

      在组合模式中,客户并不需要知道具体有哪些类,只需要知道一个接口,不需要知道哪些是父对象哪些是子对象,也就不需要写大量的判断语句了。

  • 相关阅读:
    CentOS 8下安装hadoop-3.3.0
    c# log4net安装时在AssemblyInfo中提示找不到log4net解决办法
    C#自定义类型数组排序
    C#中的隐藏方法
    VBA 按列查找小工具类似lookUp函数
    欢迎来到网络对抗路 实验八 Web综合
    利用GMSSL中ZUC算法实现对序列密码的结构性检测(代码)
    第二十一章学习笔记
    欢迎来到网络对抗路 实验七 网络欺诈防范
    数据转换考试qwq
  • 原文地址:https://www.cnblogs.com/qingfei1994/p/4261682.html
Copyright © 2011-2022 走看看