package combinationModel;

import java.util.ArrayList;
import java.util.List;

/*
 * 组合模式:
 * 将对象组合成树形结构以表示 部分-整体的层次结构,
 * 组合模式使得用户对单个对象和组合对象的使用具有一致性
 * 
 * 组合模式的优点:
 * 1、可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。
   2、客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。
   3、定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。
   4、更容 易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。
   
   缺点:
      1、使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联
 */
public class CombinationModel {
	public static void main(String[] args) {
		Component root = new Composite("root");
		root.Add(new Leaf("leaf 1"));
		root.Add(new Leaf("leaf 2"));
		
		
		Component root2 = new Composite("root 2");
		root2.Add(new Leaf("leaf 3"));
		root2.Add(new Leaf("leaf 4"));
		root.Add(root2);
		
		Component root3= new Composite("root 3");
		root3.Add(new Leaf("leaf 5"));
		root3.Add(new Leaf("leaf 6"));
		root2.Add(root3);
		
		
		//添加删除
		Leaf leaf0 = new Leaf("不删除");
		Leaf leaf = new Leaf("删除");
		root.Add(leaf0);
		root.Add(leaf);
		root.Remove(leaf);
		
		
		//展示
		root.Display(1);
		
		
		/*
		 * 实现Component的子类都有  Add  Remove  Display 方法  它们具备完全一致的接口
		 * 但是问题是非常明显的 因为left类本身不具有 Add  Remove 功能  所以实现它们是没有意义的
		 * 
		 * 
		 * 何时使用:当你发现需求是体现整体与部分结构时   以及你希望用户可以忽略组合对象与单个对象的不同,
		 * 统一使用组合结构中所有的对象时 就应该考虑组合模式了
		 */
		
	}
}

/*
 * 抽象类 指定默认行为
 */
abstract class Component{
	protected  String name;
	//构造函数
	public Component(){
	} 
	public Component(String name){
		this.name = name;
	} 
	//抽象方法
	//增加
	public abstract void Add(Component c);
	//移除
	public abstract void Remove(Component c);
	//遍历展示
	public abstract void Display(int depth); 
}
/*
 * 叶节点对象
 */
class Leaf extends Component{
	public Leaf(){
		
	}
	public Leaf(String name){
		super(name);
	}
	public void Add(Component c) {
		System.out.println("叶子节点  不能添加到节点");
	}
	public void Remove(Component c) {
		System.out.println("叶子节点  不能移除节点");
	}
	public void Display(int depth) {
		 for (int i = 0; i <depth; i++) {
				System.out.print("-");
			}
		System.out.println(name);
	}
}

/*
 * 枝叶节点的对象
 */
class Composite extends Component{
	public Composite(){
		
	}
	public Composite(String name){
		super(name);
	}
	private List<Component> children = new  ArrayList<Component>();
	public void Add(Component c) {
		children.add(c);
	}
	public void Remove(Component c) {
		children.remove(c);
	}
	public void Display(int depth) {
		 for (int i = 0; i <depth; i++) {
			System.out.print("-");
		}
		 System.out.println(name);
	  //遍历子元素  
		 for (Component c : children) {
			 //这里+2 是为了两个层级之间显示错位比较明显
			c.Display(depth+2);
		}
	 	 
	 	 
	}
	 
	
}