设计模式-组合模式

1.组合模式的定义及使用场景

组合模式也称为部分整体模式,结构型设计模式之一,组合模式比较简单,它将一组相似的对象看作一个对象处理,并根据一个树状结构来组合对象,然后提供一个统一的方法去访问相应的对象,以此忽略掉对象与对象集合之间的差别。生活中一个比较经典的例子就是组织结构的树状图。
这里写图片描述

定义:

将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性

使用场景:

  • 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理
  • 从一个整体中能够独立出部分模块或功能的场景

这里写图片描述

2. 组合模式的优缺点

2.1优点

  • 组合模式可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,它让高层模块忽略了层次的差异,方便对整个层级结构进行控制
  • 高层模块可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了高层模块的代码
  • 在组合模式中增加新的枝干构件和叶子构件都很方便,无需对现有类库进行任何修改
  • 组合模式为树形结构的面向对象实现提供了一种灵活的解决方案,通过叶子对象和枝干对象的递归组合,可以形成复杂的树形结构,但对树形结构的控制却非常简单
    ##2.2缺点
    在新增构件时不好对枝干中的构件类型进行限制,不能依赖类型系统来施加这些约束,因为在大多数情况下,他们都来自于相同的抽象层,此时,必须进行类型检查来实现,过程比较复杂

    3.注意事项

    组合模式有两种不同的实现:透明模式和安全模式(4点中为安全模式),透明模式是把用来组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构。这种模式的缺点是通过判断getChildren的返回值确认是叶子节点还是树枝节点,如果处理不当,会在运行期出现问题,安全模式它是把树枝节点和叶子节点彻底分开,树枝节点单独拥有用来组合的方法。

    4. 组合模式的实现方式

    1
    2
    3
    4
    public abstract class Component {
    public void doSomething() {
    }
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Composite extends Component {
private ArrayList<Component> componentArrayList = new ArrayList<>();

public void add(Component component) {
componentArrayList.add(component);
}

public void remove(Component component) {
componentArrayList.remove(component);
}

public ArrayList<Component> getChildren() {
return this.componentArrayList;
}

@Override
public void doSomething() {
System.out.println("Composite do something");
}
}
1
2
3
4
5
6
public class Leaf extends  Component {
@Override
public void doSomething() {
System.out.println("Leaf do someThing");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Test {

public static void main(String args[]) {
//创建一个根节点
Composite root = new Composite();
root.doSomething();
//创建一个树枝构件
Composite barnch = new Composite();
//创建一个叶子节点
Leaf leaf = new Leaf();
//建立整体
root.add(barnch);
barnch.add(leaf);
//遍历
display(root);
}

public static void display(Composite composite) {
for (Component c : composite.getChildren()) {
if (c instanceof Leaf) {
c.doSomething();
} else {
display((Composite) c);
}
}
}
}

5. 组合模式在Android中的实际应用

Android源码中关于组合模式有一个非常经典的实现,我们几乎每天都会使用到,那就是View和ViewGroup的嵌套组合。

这里写图片描述

这里省略了View和ViewGroup的一些方法,在Android的这个视图层级中,容器一定是ViewGroup,而且只有ViewGroup才能包含其他的View,例如Realyout能包含TextView、Button等,但反过来TextView不能包含Relayout,因为TextView直接继承了View,并不是一个容器,这里View的视图层级中使用的其实是一种安全的设计模式。