定义:组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 “组合对象” 的含义。
用自己的话说:使用该模式把类组合成类似树的结构,树的结点与树的子叶共同继承同一个抽象类。相对于用户来说,树的结点和树的子叶都是一样的,然后通过迭代器进行操作等等…
代码:
定义一个菜单抽象类(面向用户):
/**
* 抽象组合菜单,提供一些方法,因为子类具备两种,一种是树叶,一种是结点,所以都先抛出异常,在子类里面覆盖
* @author jiangjintai
*
*/
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();
}
public Iterator<MenuComponent> createIterator(){
return new NullIterator();
}
}
定义菜单项,即树的子叶:
/**
*
* 菜单项,表示具体的内容
* @author jiangjintai
*
*/
public class MenuItem extends MenuComponent {
String name;
String description;
boolean vegetarian;
double price;
public MenuItem(String name,String description,boolean vegetatian,double price){
this.name=name;
this.description=description;
this.vegetarian=vegetatian;
this.price=price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isVegetarian() {
return vegetarian;
}
public void setVegetarian(boolean vegetarian) {
this.vegetarian = vegetarian;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public void print(){
System.out.print(this.getName());
if(isVegetarian()){
System.out.print("(v)");
}
System.out.println(this.getPrice());
System.out.println("--"+this.getDescription());
}
}
定义一个迭代器(迭代器与组合模式的混合运用):
/**
* 为了能对其中的所有元素进行遍历
* @author jiangjintai
*
*/
public class CompositeIterator implements Iterator<MenuComponent> {
//内部包含一个栈的数据结构
Stack<Iterator<MenuComponent>> stack = new Stack<Iterator<MenuComponent>>();
/**
*
*/
public CompositeIterator(Iterator<MenuComponent> iterator) {
stack.push(iterator);
}
/* (非 Javadoc)
* @see java.util.Iterator#hasNext()
*/
@Override
public boolean hasNext() {
if(stack.empty()){
return false;
}else{
Iterator<MenuComponent> iterator = stack.peek();
if(!iterator.hasNext()){
stack.pop();
return hasNext();
}else{
return true;
}
}
}
/* (非 Javadoc)
* @see java.util.Iterator#next()
*/
@Override
public MenuComponent next() {
if(hasNext()){
Iterator<MenuComponent> iterator = stack.peek();
MenuComponent component = iterator.next();
if(component instanceof Menu){
stack.push(component.createIterator());
}
return component;
}else{
return null;
}
}
/* (非 Javadoc)
* @see java.util.Iterator#remove()
*/
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
定义一个菜单项,即树的结点:
/**
* 菜单,不同于菜单项,处于结点位置,拥有子节点
* @author jiangjintai
*
*/
public class Menu extends MenuComponent {
ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
String name;
String description;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setDescription(String description) {
this.description = description;
}
public Menu(String name,String description){
this.name=name;
this.description=description;
}
public void add(MenuComponent menuComponent){
this.menuComponents.add(menuComponent);
}
public void remove(MenuComponent menuComponent){
this.menuComponents.remove(menuComponent);
}
public MenuComponent getChild(int i){
return this.menuComponents.get(i);
}
public String getDescription(){
return description;
}
@Override
public void print(){
System.out.print("\n"+this.getName());
System.out.print(","+this.getDescription());
System.out.println("---------------------");
Iterator<MenuComponent> iterator = menuComponents.iterator();
while(iterator.hasNext()){
MenuComponent menuComponent = iterator.next();
menuComponent.print();
}
}
//与迭代模式的组合应用
public Iterator<MenuComponent> createIterator(){
return new CompositeIterator(menuComponents.iterator());
}
}
测试:
public static void main(String[] args){
MenuComponent chinaMenu= new Menu("中餐","中国菜特色");
MenuComponent beijingMenu = new Menu("北京菜","北京菜,中国最有特色");
MenuComponent chaozhouMenu = new Menu("潮州菜","潮州菜,小地方特色");
MenuComponent cai1 = new MenuItem("烤鸭", "北京特色", true, 66d);
beijingMenu.add(cai1);
MenuComponent cai2 = new MenuItem("肠粉", "潮州特色", true, 6d);
MenuComponent cai3 = new MenuItem("无米果", "潮州特色", true, 5d);
MenuComponent cai4 = new MenuItem("咸水果", "潮州特色", true, 5d);
MenuComponent cai5 = new MenuItem("春饼", "潮州特色", true, 2d);
chaozhouMenu.add(cai2);
chaozhouMenu.add(cai3);
chaozhouMenu.add(cai4);
chaozhouMenu.add(cai5);
chinaMenu.add(chaozhouMenu);
chinaMenu.add(beijingMenu);
chinaMenu.print();
}
结果:
中餐,中国菜特色---------------------
潮州菜,潮州菜,小地方特色---------------------
肠粉(v)6.0
--潮州特色
无米果(v)5.0
--潮州特色
咸水果(v)5.0
--潮州特色
春饼(v)2.0
--潮州特色
北京菜,北京菜,中国最有特色---------------------
烤鸭(v)66.0
--北京特色