博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之组合模式
阅读量:5036 次
发布时间:2019-06-12

本文共 5107 字,大约阅读时间需要 17 分钟。

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

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

 

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

  组合模式的类图如下:

 

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

   

 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
menuComponents; String name; public Menu(String name) { this.name=name; menuComponents=new ArrayList
(); } 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();	}}

    结果是

    

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

转载于:https://www.cnblogs.com/qingfei1994/p/4261682.html

你可能感兴趣的文章
我对你的期望有点过了
查看>>
微信小程序wx:key以及wx:key=" *this"详解:
查看>>
下拉框比较符
查看>>
2.2.5 因子的使用
查看>>
css选择器
查看>>
photoplus
查看>>
Python 拓展之推导式
查看>>
[Leetcode] DP-- 474. Ones and Zeroes
查看>>
80X86寄存器详解<转载>
查看>>
c# aop讲解
查看>>
iterable与iterator
查看>>
返回顶部(动画)
查看>>
webpack+react+antd 单页面应用实例
查看>>
Confluence 6 SQL Server 数据库驱动修改
查看>>
Confluence 6 通过 SSL 或 HTTPS 运行 - 备注和问题解决
查看>>
【47.76%】【Round #380B】Spotlights
查看>>
Git(使用码云)
查看>>
分享Java web 开发必游之路
查看>>
IIS初始化(预加载),解决第一次访问慢,程序池被回收问题(转载)
查看>>
Bean的Scope
查看>>