组合模式:将对象组合成树形结构以表示“整体-部分”的层次结构,一种对象结构型模式。
由于在软件开发中存在大量的树形结构,因此组合模式是一种使用频率较高的结构型设计模式,Java SE中的AWT和Swing包的设计就基于组合模式。除此以外,在XML解析、组织结构树处理、文件系统设计等领域,组合模式都得到了广泛应用。
组合模式角色:
抽象构件(Component)角色:这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。
树枝构件(Composite)角色:代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及getChild()。
树叶构件(Leaf)角色:树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。
1、优点
(1)组合模式可以清晰的定义分层次的复杂对象,表示对象的全部或部分层次,它让客户端忽略了层次的差异,方便对整个层次结构进行控制。
(2)客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码。
(3)在组合模式中增加新的容器构件和叶子构件都很方便,无须对现有类库进行任何修改,符合“开闭原则”。
(4)组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和容器对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单。
2、缺点
(1)使得设计更加复杂,客户端需要花更多时间理清类之间的层次关系。
(2)在增加新构件时很难对容器中的构件类型进行限制。
示例:
抽象构件(Component)角色:
public abstract class Compose {
protected String name;
protected void add(Compose compose) {
throw new RuntimeException("不支持该操作");
}
protected void del(int index) {
throw new RuntimeException("不支持该操作");
}
protected List<Compose> getChilds() {
throw new RuntimeException("不支持该操作");
}
protected abstract void oprater();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
树枝构件(Composite)角色:
public class Composite extends Compose{
private List<Compose>composeList=new ArrayList<>();
@Override
protected void add(Compose compose) {
composeList.add(compose);
}
@Override
protected void del(int index) {
composeList.remove(index);
}
@Override
protected List<Compose> getChilds() {
return composeList;
}
@Override
protected void oprater() {
System.out.println(name);
for (int i = 0; i < composeList.size(); i++) {
System.out.print(composeList.get(i).getName());
}
System.out.println();
}
}
树叶构件(Leaf)角色:
public class Leaf extends Compose{
@Override
protected void oprater() {
System.out.println(name);
}
}
测试示例:
public class test {
public static void main(String[] args) {
Composite composite=new Composite();
composite.setName("root");
Composite composite1=new Composite();
composite1.setName("子节点1");
composite.add(composite1);
Leaf leaf=new Leaf();
leaf.setName("子叶子节点");
composite.add(leaf);
composite.oprater();
}
}