3. 组合模式(Composite Pattern)
组合模式可以让我们把对象按照树状结构进行组织,可以想象成菜单的概念,菜单下面有子菜单,也会有菜单项,使用了组合模式,我们可以在"子菜单"(组合对象)和"菜单项"(个体对象)上使用相同的操作,也就是说在多数的情况下是不用去区分它们的。
我们还是来举个例子,就是上边说的菜单的例子,我们来建立的一个结构来表示菜单,子菜单和菜单项的组合。
首先定义一个菜单组件的抽象基类,它定义了菜单操作的基本方法,比如#add(),#remove(),#getChild();另外还定义了菜单的行为方法,#getName(),printMenu()。
接下来就是菜单项和菜单类了,它们都是MenuComponent的子类。
通过这种方式,我们就可以在实现一种"整体 -- 局部"关系的同时,又实现了对组合对象与单一对象的统一对待,简化了编程。
接下来可以看一下使用上边例子的客户端代码,这个客户端模拟了eclipse的菜单。
它的运行结果如下:
这样,组合模式就基本讲解完了,最后给出组合模式的类图:
组合模式可以让我们把对象按照树状结构进行组织,可以想象成菜单的概念,菜单下面有子菜单,也会有菜单项,使用了组合模式,我们可以在"子菜单"(组合对象)和"菜单项"(个体对象)上使用相同的操作,也就是说在多数的情况下是不用去区分它们的。
我们还是来举个例子,就是上边说的菜单的例子,我们来建立的一个结构来表示菜单,子菜单和菜单项的组合。
首先定义一个菜单组件的抽象基类,它定义了菜单操作的基本方法,比如#add(),#remove(),#getChild();另外还定义了菜单的行为方法,#getName(),printMenu()。
- /**
- * 抽象菜单组件基类<br>
- *
- * @author archer
- *
- */
- public abstract class MenuComponent {
- /**
- * 增加菜单组件(可能是菜单项或者子菜单)<br>
- *
- * @param menuComponent
- */
- public void add(MenuComponent menuComponent) {
- throw new UnsupportedOperationException();
- }
- /**
- * 移除菜单组件<br>
- *
- * @param menuComponent
- */
- public void remove(MenuComponent menuComponent) {
- throw new UnsupportedOperationException();
- }
- /**
- * 返回子菜单组件<br>
- *
- * @param i
- * @return
- */
- public MenuComponent getChild(int i) {
- throw new UnsupportedOperationException();
- }
- /**
- * 返回菜单项目或者菜单的名字<br>
- *
- * @return
- */
- public String getName() {
- throw new UnsupportedOperationException();
- }
- /**
- * 打印菜单<br>
- *
- */
- public void printMenu() {
- throw new UnsupportedOperationException();
- }
- }
/**
* 抽象菜单组件基类<br>
*
* @author archer
*
*/
public abstract class MenuComponent {
/**
* 增加菜单组件(可能是菜单项或者子菜单)<br>
*
* @param menuComponent
*/
public void add(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
/**
* 移除菜单组件<br>
*
* @param menuComponent
*/
public void remove(MenuComponent menuComponent) {
throw new UnsupportedOperationException();
}
/**
* 返回子菜单组件<br>
*
* @param i
* @return
*/
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
/**
* 返回菜单项目或者菜单的名字<br>
*
* @return
*/
public String getName() {
throw new UnsupportedOperationException();
}
/**
* 打印菜单<br>
*
*/
public void printMenu() {
throw new UnsupportedOperationException();
}
}
接下来就是菜单项和菜单类了,它们都是MenuComponent的子类。
- /**
- * 菜单项<br>
- *
- * @author archer
- *
- */
- public class MenuItem extends MenuComponent {
- private String name = null;
- public MenuItem(String name) {
- this.name = name;
- }
- @Override
- public String getName() {
- return this.name;
- }
- @Override
- public void printMenu() {
- System.out.println("\t" + this.getName());
- }
- }
- /**
- * 菜单<br>
- *
- * @author archer
- *
- */
- public class Menu extends MenuComponent {
- private List<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
- private String name = null;
- public Menu(String name) {
- this.name = name;
- }
- @Override
- public String getName() {
- return this.name;
- }
- @Override
- public void add(MenuComponent menuComponent) {
- menuComponents.add(menuComponent);
- }
- @Override
- public MenuComponent getChild(int i) {
- return menuComponents.get(i);
- }
- @Override
- public void remove(MenuComponent menuComponent) {
- menuComponents.remove(menuComponent);
- }
- @Override
- public void printMenu() {
- System.out.println(this.getName());
- System.out.println("--------------------");
- // 这里用到了Iterator模式
- Iterator<MenuComponent> iter = menuComponents.iterator();
- while (iter.hasNext()) {
- MenuComponent component = iter.next();
- component.printMenu();
- }
- }
- }
/**
* 菜单项<br>
*
* @author archer
*
*/
public class MenuItem extends MenuComponent {
private String name = null;
public MenuItem(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void printMenu() {
System.out.println("\t" + this.getName());
}
}
/**
* 菜单<br>
*
* @author archer
*
*/
public class Menu extends MenuComponent {
private List<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
private String name = null;
public Menu(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
@Override
public void add(MenuComponent menuComponent) {
menuComponents.add(menuComponent);
}
@Override
public MenuComponent getChild(int i) {
return menuComponents.get(i);
}
@Override
public void remove(MenuComponent menuComponent) {
menuComponents.remove(menuComponent);
}
@Override
public void printMenu() {
System.out.println(this.getName());
System.out.println("--------------------");
// 这里用到了Iterator模式
Iterator<MenuComponent> iter = menuComponents.iterator();
while (iter.hasNext()) {
MenuComponent component = iter.next();
component.printMenu();
}
}
}
通过这种方式,我们就可以在实现一种"整体 -- 局部"关系的同时,又实现了对组合对象与单一对象的统一对待,简化了编程。
接下来可以看一下使用上边例子的客户端代码,这个客户端模拟了eclipse的菜单。
- public class Client {
- public static void main(String[] args) {
- // 总菜单
- MenuComponent allMenu = new Menu("Eclipse Menu DEMO");
- // "File"子菜单
- MenuComponent fileMenu = new Menu("File");
- // "New"子菜单
- MenuComponent newMenu = new Menu("New");
- // "New"的菜单项
- MenuComponent EAPMenuItem = new MenuItem("Enterprise Application Project");
- MenuComponent DWPMenuItem = new MenuItem("Dynamic Web Project");
- MenuComponent EJBMenuItem = new MenuItem("EJB Project");
- newMenu.add(EAPMenuItem);
- newMenu.add(DWPMenuItem);
- newMenu.add(EJBMenuItem);
- fileMenu.add(newMenu);
- // "Edit"子菜单
- MenuComponent editMenu = new Menu("Edit");
- // "Edit"的菜单项
- MenuComponent CutMenuItem = new MenuItem("Cut");
- MenuComponent CopyMenuItem = new MenuItem("Copy");
- MenuComponent PasteMenuItem = new MenuItem("Paste");
- editMenu.add(CutMenuItem);
- editMenu.add(CopyMenuItem);
- editMenu.add(PasteMenuItem);
- allMenu.add(fileMenu);
- allMenu.add(editMenu);
- // 打印菜单
- allMenu.printMenu();
- }
- }
public class Client {
public static void main(String[] args) {
// 总菜单
MenuComponent allMenu = new Menu("Eclipse Menu DEMO");
// "File"子菜单
MenuComponent fileMenu = new Menu("File");
// "New"子菜单
MenuComponent newMenu = new Menu("New");
// "New"的菜单项
MenuComponent EAPMenuItem = new MenuItem("Enterprise Application Project");
MenuComponent DWPMenuItem = new MenuItem("Dynamic Web Project");
MenuComponent EJBMenuItem = new MenuItem("EJB Project");
newMenu.add(EAPMenuItem);
newMenu.add(DWPMenuItem);
newMenu.add(EJBMenuItem);
fileMenu.add(newMenu);
// "Edit"子菜单
MenuComponent editMenu = new Menu("Edit");
// "Edit"的菜单项
MenuComponent CutMenuItem = new MenuItem("Cut");
MenuComponent CopyMenuItem = new MenuItem("Copy");
MenuComponent PasteMenuItem = new MenuItem("Paste");
editMenu.add(CutMenuItem);
editMenu.add(CopyMenuItem);
editMenu.add(PasteMenuItem);
allMenu.add(fileMenu);
allMenu.add(editMenu);
// 打印菜单
allMenu.printMenu();
}
}
它的运行结果如下:
- Eclipse Menu DEMO
- --------------------
- File
- --------------------
- New
- --------------------
- Enterprise Application Project
- Dynamic Web Project
- EJB Project
- Edit
- --------------------
- Cut
- Copy
- Paste
Eclipse Menu DEMO
--------------------
File
--------------------
New
--------------------
Enterprise Application Project
Dynamic Web Project
EJB Project
Edit
--------------------
Cut
Copy
Paste
这样,组合模式就基本讲解完了,最后给出组合模式的类图: