了解设计模式 之 结构模式(三) -- 组合模式

 
3. 组合模式(Composite Pattern)

组合模式可以让我们把对象按照树状结构进行组织,可以想象成菜单的概念,菜单下面有子菜单,也会有菜单项,使用了组合模式,我们可以在"子菜单"(组合对象)和"菜单项"(个体对象)上使用相同的操作,也就是说在多数的情况下是不用去区分它们的。

我们还是来举个例子,就是上边说的菜单的例子,我们来建立的一个结构来表示菜单,子菜单和菜单项的组合。

首先定义一个菜单组件的抽象基类,它定义了菜单操作的基本方法,比如#add(),#remove(),#getChild();另外还定义了菜单的行为方法,#getName(),printMenu()。

Java代码 复制代码  收藏代码
  1. /**  
  2.  * 抽象菜单组件基类<br>  
  3.  *   
  4.  * @author archer  
  5.  *   
  6.  */  
  7. public abstract class MenuComponent {   
  8.   
  9.     /**  
  10.      * 增加菜单组件(可能是菜单项或者子菜单)<br>  
  11.      *   
  12.      * @param menuComponent  
  13.      */  
  14.     public void add(MenuComponent menuComponent) {   
  15.         throw new UnsupportedOperationException();   
  16.     }   
  17.   
  18.     /**  
  19.      * 移除菜单组件<br>  
  20.      *   
  21.      * @param menuComponent  
  22.      */  
  23.     public void remove(MenuComponent menuComponent) {   
  24.         throw new UnsupportedOperationException();   
  25.     }   
  26.   
  27.     /**  
  28.      * 返回子菜单组件<br>  
  29.      *   
  30.      * @param i  
  31.      * @return  
  32.      */  
  33.     public MenuComponent getChild(int i) {   
  34.         throw new UnsupportedOperationException();   
  35.     }   
  36.   
  37.     /**  
  38.      * 返回菜单项目或者菜单的名字<br>  
  39.      *   
  40.      * @return  
  41.      */  
  42.     public String getName() {   
  43.         throw new UnsupportedOperationException();   
  44.     }   
  45.   
  46.     /**  
  47.      * 打印菜单<br>  
  48.      *   
  49.      */  
  50.     public void printMenu() {   
  51.         throw new UnsupportedOperationException();   
  52.     }   
  53. }  
	/**
	 * 抽象菜单组件基类<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的子类。

Java代码 复制代码  收藏代码
  1. /**  
  2.  * 菜单项<br>  
  3.  *   
  4.  * @author archer  
  5.  *   
  6.  */  
  7. public class MenuItem extends MenuComponent {   
  8.     private String name = null;   
  9.   
  10.     public MenuItem(String name) {   
  11.         this.name = name;   
  12.     }   
  13.   
  14.     @Override  
  15.     public String getName() {   
  16.         return this.name;   
  17.     }   
  18.   
  19.     @Override  
  20.     public void printMenu() {   
  21.         System.out.println("\t" + this.getName());   
  22.     }   
  23. }   
  24.   
  25. /**  
  26.  * 菜单<br>  
  27.  *   
  28.  * @author archer  
  29.  *   
  30.  */  
  31. public class Menu extends MenuComponent {   
  32.     private List<MenuComponent> menuComponents = new ArrayList<MenuComponent>();   
  33.   
  34.     private String name = null;   
  35.   
  36.     public Menu(String name) {   
  37.         this.name = name;   
  38.     }   
  39.   
  40.     @Override  
  41.     public String getName() {   
  42.         return this.name;   
  43.     }   
  44.   
  45.     @Override  
  46.     public void add(MenuComponent menuComponent) {   
  47.         menuComponents.add(menuComponent);   
  48.     }   
  49.   
  50.     @Override  
  51.     public MenuComponent getChild(int i) {   
  52.         return menuComponents.get(i);   
  53.     }   
  54.   
  55.     @Override  
  56.     public void remove(MenuComponent menuComponent) {   
  57.         menuComponents.remove(menuComponent);   
  58.     }   
  59.   
  60.     @Override  
  61.     public void printMenu() {   
  62.         System.out.println(this.getName());   
  63.         System.out.println("--------------------");   
  64.   
  65.         // 这里用到了Iterator模式   
  66.         Iterator<MenuComponent> iter = menuComponents.iterator();   
  67.   
  68.         while (iter.hasNext()) {   
  69.             MenuComponent component = iter.next();   
  70.             component.printMenu();   
  71.         }   
  72.   
  73.     }   
  74.   
  75. }  
	/**
	 * 菜单项<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的菜单。

Java代码 复制代码  收藏代码
  1. public class Client {   
  2.   
  3.     public static void main(String[] args) {   
  4.         // 总菜单   
  5.         MenuComponent allMenu = new Menu("Eclipse Menu DEMO");   
  6.   
  7.         // "File"子菜单   
  8.         MenuComponent fileMenu = new Menu("File");   
  9.            
  10.         // "New"子菜单   
  11.         MenuComponent newMenu = new Menu("New");   
  12.            
  13.         // "New"的菜单项   
  14.         MenuComponent EAPMenuItem = new MenuItem("Enterprise Application Project");   
  15.         MenuComponent DWPMenuItem = new MenuItem("Dynamic Web Project");   
  16.         MenuComponent EJBMenuItem = new MenuItem("EJB Project");   
  17.   
  18.         newMenu.add(EAPMenuItem);   
  19.         newMenu.add(DWPMenuItem);   
  20.         newMenu.add(EJBMenuItem);   
  21.   
  22.         fileMenu.add(newMenu);   
  23.   
  24.         // "Edit"子菜单   
  25.         MenuComponent editMenu = new Menu("Edit");   
  26.            
  27.         // "Edit"的菜单项   
  28.         MenuComponent CutMenuItem = new MenuItem("Cut");   
  29.         MenuComponent CopyMenuItem = new MenuItem("Copy");   
  30.         MenuComponent PasteMenuItem = new MenuItem("Paste");   
  31.   
  32.         editMenu.add(CutMenuItem);   
  33.         editMenu.add(CopyMenuItem);   
  34.         editMenu.add(PasteMenuItem);   
  35.   
  36.         allMenu.add(fileMenu);   
  37.         allMenu.add(editMenu);   
  38.   
  39.         // 打印菜单   
  40.         allMenu.printMenu();   
  41.     }   
  42.   
  43. }  
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();
	}

}


它的运行结果如下:

Java代码 复制代码  收藏代码
  1. Eclipse Menu DEMO   
  2. --------------------   
  3. File   
  4. --------------------   
  5. New   
  6. --------------------   
  7.     Enterprise Application Project   
  8.     Dynamic Web Project   
  9.     EJB Project   
  10. Edit   
  11. --------------------   
  12.     Cut   
  13.     Copy   
  14.     Paste  
Eclipse Menu DEMO
--------------------
File
--------------------
New
--------------------
	Enterprise Application Project
	Dynamic Web Project
	EJB Project
Edit
--------------------
	Cut
	Copy
	Paste


这样,组合模式就基本讲解完了,最后给出组合模式的类图:


  • 大小: 18.2 KB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值