結構型-組合模式

小弟季義欽發表於2013-03-28
package composite;
import java.util.ArrayList;
import java.util.Iterator;
/**
 * @author jiq
 * 型別:Structural
 * 定義: 組合模式(Composite)允許你講物件組合成屬性結構來表現“整體/部分”的層次結構。
 * 		組合能讓客戶以一致的方式對待這個層次結構中的個別物件以及物件組合。
 * 
 * 用途: 這個模式能夠建立一個樹形結構,在同一個結構中處理巢狀選單和選單項。通過將
 * 		選單和選單項放在相同的結構中,我們建立了一個“整體/部分”層次結構。我們將其
 * 		視為一個豐富的大選單,一旦有了這個大選單,我們就可以使用這個模式來“統一處理
 * 		個別物件和組合物件”。這意味著我們可以對整個選單結構應用相同的操作,比如列印。
 * 		--- 當你有一個物件的集合,他們彼此之間有“整體/部分”的關係,並且你想用一致的
 * 			方法對待這些物件的時候,你就需要組合模式。
 * 		--- “整體/部分”關係指的是,舉個例子,使用者介面,經常會看到一個頂層元件(Frame
 * 			或Panel)包含其他元件(選單,文字,按鈕等),所有這些單獨看來都是部分,他們
 * 			所有加起來就是整體。
 * 		--- “一致的方法對待這些物件”是指“組合物件”和“葉節點”物件具有共同的方法可以呼叫。
 * 			但是他們各自回做出正確的事情,組合物件會叫他的所有元件(組合物件或者葉節點)顯示。
 * 
 * 最大優勢:客戶不需要在操心自己面對的是組合物件還是葉節點物件,客戶只需要對整個結構呼叫
 * 			一個方法並執行操作就可以了。 
 * 應用: 檔案系統中的File物件,既可以是目錄(組合物件,包含目錄或者檔案),也可以是檔案(葉節點)。
 * 		
 */

//抽象選單元件,所有方法不是必須實現,所以沒有宣告為abstract
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 double getPrice() {
		throw new UnsupportedOperationException();	}
	public void print() {
		throw new UnsupportedOperationException();	}
}

//選單(組合物件)
class Menu extends MenuComponent {
	//選單包含其它的(選單/選單項)作為子節點,即組合物件中包含其他元件(組合物件/葉節點)
	ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>();
	String name;  
	public Menu(String name) {
		this.name = name; 
	}	
	public void add(MenuComponent menuComponent) {
		menuComponents.add(menuComponent);
	} 
	public void remove(MenuComponent menuComponent) {
		menuComponents.remove(menuComponent);
	} 
	public MenuComponent getChild(int i) {
		return (MenuComponent)menuComponents.get(i);
	} 
	public String getName() { return name; }
 
	public void print() {
		System.out.print("\n" + getName());
		System.out.println("---------------------");
		//使用迭代器模式遍歷所有子節點
		Iterator<MenuComponent> iterator = menuComponents.iterator();
		while (iterator.hasNext()) {
			MenuComponent menuComponent = (MenuComponent)iterator.next();
			menuComponent.print();
		}
	}
}

//選單項(葉節點物件)
class MenuItem extends MenuComponent {
	String name;
	double price;
    
	public MenuItem(String name,double price) { 
		this.name = name;
		this.price = price;
	}
	public String getName() { return name; }	
	public double getPrice() { return price; }
	public void print() {
		System.out.print("  " + getName());
		System.out.println(", " + getPrice());
	}
}

//測試組合模式
public class Composite {
	public static void main(String[] args) {
		MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU");
		MenuComponent dinerMenu = new Menu("DINER MENU");
		MenuComponent cafeMenu = new Menu("CAFE MENU");
		MenuComponent coffeeMenu = new Menu("COFFEE MENU");
		
		//大選單的根節點
		MenuComponent allMenus = new Menu("ALL MENUS");
  
		//新增節點
		allMenus.add(pancakeHouseMenu);
		allMenus.add(dinerMenu);
		allMenus.add(cafeMenu);
		pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast",2.99));
		pancakeHouseMenu.add(new MenuItem("Regular P Breakfast",2.22));
		dinerMenu.add(new MenuItem("Vegetarian BLT",3.99));
		dinerMenu.add(new MenuItem("BLT",2.99));
		cafeMenu.add(new MenuItem("Burrito",4.29));
		cafeMenu.add(coffeeMenu);
		coffeeMenu.add(new MenuItem("Coffee Cake",1.59));
		allMenus.print();	//列印整個大選單
	}
}

相關文章