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);
}


}


}