说明
组合模式(Composite Pattern),又叫部分整体模式,是一种结构型模式。它将对象组合成树形结构以表示"部分-整体"的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性
应用场景
部分、整体场景,如树形菜单,文件、文件夹的管理
模式特征
角色 | 说明 | 举栗 |
---|---|---|
抽象根节点(Component) | 定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性 | TransparentComponent、SecurityComponent |
树枝节点(Composite) | 定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构 | TransparentComposite、SecurityComposite |
叶子节点(Leaf) | 叶子节点对象,其下再无分支,是系统层次遍历的最小单位 | TransparentLeaf、SecurityLeaf |
实现方式
- 透明模式:透明模式是把组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,这样做的好处就是叶子节点和树枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为Leaf类本身不具备add()、remove()方法的功能,所以实现它是没有意义的
- 安全模式:安全模式是把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全。但由于不够透明,所以树叶节点和树枝节点将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
UML
透明模式
安全模式
代码实现
透明模式
- 抽象根节点:TransparentComponent
public abstract class TransparentComponent {
protected String name;
public TransparentComponent(String name){
this.name = name;
}
//添加一个子节点
public abstract void add(TransparentComponent component);
//移除一个子节点
public abstract void remove(TransparentComponent component);
//展示节点信息
public abstract void display(int depth);
}
- 树枝节点:TransparentComposite
public class TransparentComposite extends TransparentComponent {
//子节点容器
private List<TransparentComponent> components = new ArrayList<>();
public TransparentComposite(String name) {
super(name);
}
@Override
public void add(TransparentComponent component) {
this.components.add(component);
}
@Override
public void remove(TransparentComponent component) {
this.components.remove(component);
}
@Override
public void display(int depth) {
//输出树形结构
for (int i = 0; i < depth; i++) {
System.out.print('-');
}
System.out.println(name);
//下级遍历
for (TransparentComponent component : components) {
component.display(depth + 1);
}
}
}
- 叶子节点:TransparentLeaf
public class TransparentLeaf extends TransparentComponent {
public TransparentLeaf(String name) {
super(name);
}
//叶子节点不允许添加component
@Override
public void add(TransparentComponent component) {
throw new UnsupportedOperationException("Leaf cannot add component");
}
//叶子节点不允许删除component
@Override
public void remove(TransparentComponent component) {
throw new UnsupportedOperationException("Leaf have not component to remove");
}
@Override
public void display(int depth) {
//输出树形结构的叶子节点
for (int i = 0; i < depth; i++) {
System.out.print('-');
}
System.out.println(name);
}
}
- 客户端测试类
public class Client {
public static void main(String[] args) {
//创建根节点及其叶子节点
TransparentComposite root = new TransparentComposite("root");
root.add(new TransparentLeaf("Leaf 1_1"));
root.add(new TransparentLeaf("Leaf 1_2"));
//创建二层树枝节点及其叶子节点,并将其添加到根节点
TransparentComposite branch = new TransparentComposite("Branch 1_1");
branch.add(new TransparentLeaf("Leaf 2_1"));
branch.add(new TransparentLeaf("Leaf 2_2"));
root.add(branch);
//创建三层树枝节点及其叶子节点,并将其添加到branch
TransparentComposite branch1 = new TransparentComposite("Branch 2_1");
branch1.add(new TransparentLeaf("Leaf 3_1"));
branch1.add(new TransparentLeaf("Leaf 3_2"));
branch.add(branch1);
root.display(1);
}
}
安全模式
- 抽象根节点:SecurityComponent
public abstract class SecurityComponent {
protected String name;
public SecurityComponent(String name){
this.name = name;
}
//展示节点信息
public abstract void display(int depth);
}
- 树枝节点:SecurityComposite
public class SecurityComposite extends SecurityComponent {
//子节点容器
private List<SecurityComponent> components = new ArrayList<>();
public SecurityComposite(String name) {
super(name);
}
public void add(SecurityComponent component) {
this.components.add(component);
}
public void remove(SecurityComponent component) {
this.components.remove(component);
}
@Override
public void display(int depth) {
//输出树形结构
for (int i = 0; i < depth; i++) {
System.out.print('-');
}
System.out.println(name);
//下级遍历
for (SecurityComponent component : components) {
component.display(depth + 1);
}
}
}
- 叶子节点:SecurityLeaf
public class SecurityLeaf extends SecurityComponent {
public SecurityLeaf(String name) {
super(name);
}
@Override
public void display(int depth) {
//输出树形结构的叶子节点
for (int i = 0; i < depth; i++) {
System.out.print('-');
}
System.out.println(name);
}
}
- 客户端测试类
public class Client {
public static void main(String[] args) {
//创建根节点及其叶子节点
SecurityComposite root = new SecurityComposite("root");
root.add(new SecurityLeaf("Leaf 1_1"));
root.add(new SecurityLeaf("Leaf 1_2"));
//创建二层树枝节点及其叶子节点,并将其添加到根节点
SecurityComposite branch = new SecurityComposite("Branch 1_1");
branch.add(new SecurityLeaf("Leaf 2_1"));
branch.add(new SecurityLeaf("Leaf 2_2"));
root.add(branch);
//创建三层树枝节点及其叶子节点,并将其添加到branch
SecurityComposite branch1 = new SecurityComposite("Branch 2_1");
branch1.add(new SecurityLeaf("Leaf 3_1"));
branch1.add(new SecurityLeaf("Leaf 3_2"));
branch.add(branch1);
root.display(1);
}
}
结果
-root
--Leaf 1_1
--Leaf 1_2
--Branch 1_1
---Leaf 2_1
---Leaf 2_2
---Branch 2_1
----Leaf 3_1
----Leaf 3_2
优缺点
优点
高层模块调用简单。一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,高层模块不必关心自己处理的是单个对象还是整个组合结构。
缺点
使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒转原则