组合模式实际上就是让客户端不再区分操作的是组合对象还是叶子对象,而是以一个统一的方式来操作。
组合模式的本质:统一叶子对象和组合对象。
组合模式通过把叶子对象当成特殊的组合对象看待,从而对叶子对象和组合对象一视同仁,全部当成了Component对象,有机地统一了叶子对象和组合对象。
正是因为统一了叶子对象和组合对象,在将对象构建成树型结构的时候,才不需要做区分,反正是组件对象里面包含其他的组件对象,如此递归下去;也才使得对于树形结构的操作变得简单,不管对象类型,统一操作。
建议在以下情况中选用组合模式。
组合模式有以下优点。
定义了包含基本对象和组合对象的类层次结构
在组合模式中,基本对象可以被组合成复杂的组合对象,而组合对象又可以组合成更复杂的组合对象,可以不断地递归组合下去,从而构成一个统一的组合对象的类层次结构。
统一了组合对象和叶子对象
在组合模式中,可以把叶子对象当作特殊的组合对象看待,为它们定义统一的父类,从而把组合对象和叶子对象的行为统一起来。
简化了客户端调用
组合模式通过统一组合对象和叶子对象,使得客户端在使用它们的时候,不需要再去区分它们,客户不关心使用的到底是什么类型的对象,这就大大简化了客户端的使用。
更容易扩展
由于客户端是统一地面对Component来操作,因此,新定义的Composite或 Leaf子类能够很容易地与已有的结构一起工作,而客户端不需要为增添了新的组件类而改变。
一个学校有多个学院,一个学院有多个专业,抽象成一个树形结构
学校和学院都可以有叶子节点,可以共用一个类(Composite),叶子节点单独用一个类(Leaf)
1.父接口
/**
* @description:父接口
*/
@Data
public abstract class Component {
/**
* 打印
* @param preStr
*/
public abstract void print(String preStr);
/**
* 添加对象
* @param component
*/
public void add(Component component){
throw new UnsupportedOperationException("对象不支持这个功能");
}
/**
* 移除对象
* @param component
*/
public void remove(Component component){
throw new UnsupportedOperationException("对象不支持这个功能");
}
}
2.组合对象类
/**
* @description:组合对象(学校、学院)
*/
public class Composite extends Component {
private String name;
private List<Component> list = new ArrayList<>();
public Composite(String name) {
this.name = name;
}
@Override
public void print(String preStr) {
System.out.println(preStr+"+"+this.name);
if (this.list!=null){
preStr+=" ";
for (Component c: list){
c.print(preStr);
}
}
}
@Override
public void add(Component component) {
list.add(component);
}
@Override
public void remove(Component component) {
list.remove(component);
}
}
3.叶子类
/**
* @description:叶子对象(系)
*/
@AllArgsConstructor
public class Leaf extends Component {
/**
* 叶子节点名字
*/
private String name;
@Override
public void print(String preStr) {
System.out.println(preStr+"-"+name);
}
}
4.测试类
public class Client {
public static void main(String[] args) {
//学校
Component university = new Composite("清华大学");
//学院
Component computerCollege = new Composite("计算机学院");
Component mathCollege = new Composite("数学学院");
//学院添加系
computerCollege.add(new Leaf("软件"));
computerCollege.add(new Leaf("电子"));
computerCollege.add(new Leaf("通信"));
mathCollege.add(new Leaf("概率"));
mathCollege.add(new Leaf("统计"));
//学校添加学院
university.add(computerCollege);
university.add(mathCollege);
//输出学校结构
university.print("");
}
}
这样就实现了类似树形结构