组合模式——对象树的实现

文章目录

    • 1. 定义
    • 2. 设计
    • 3. 应用
      • 3.1. MyBatis:Plugin
      • 3.2. Android:View 树
    • 4. 特点
      • 4.1. 优势
      • 4.2. 缺点

Demo 地址: https://github.com/ooblee/HelloDesignPattern

1. 定义

组合模式(Composite Pattern):组合多个对象形成树形结构以表示具有“整体—部分”关系的层次结构。组合模式对单个对象(即叶子对象)和组合对象(即容器对象)的使用具有一致性,组合模式又可以称为“整体—部分”(Part-Whole)模式,它是一种对象结构型模式。

可以在现实中找到模型。

比如公司的组织架构就是一棵树,总部下来会有财务、行政、人力、研发、市场等部门,每个部门下面又会有不同的子部门。

又比如文件结构。整体文件结构是一个树形结构,目录和文件,一个目录下面又会有子目录或者文件。

虽然一个是容器一个是叶子,但我们喜欢对这个树的所有节点都有一致的访问方式。

比如有同样的方式可以获取到大小、创建时间、修改时间,可以使用相同的接口进行增加、删除和修改。

组合模式——对象树的实现_第1张图片

2. 设计

主要角色:

  • 抽象构件,定义叶子和容器共有的方法。定义了访问子构件的方法,比如增加、修改、删除、获取。
  • 叶子构件,实现抽象构件,因为没有子节点,可以使用异常处理访问子构件的方法。
  • 容器构件,实现抽象构件,实现访问子构件的方法。

类图:

组合模式——对象树的实现_第2张图片

使用者面向抽象构件编程,可以不用区分容器和叶子,统一处理。

抽象构件类,为了方便打印树,我们在执行方法加了一个深度信息,用来打印当前节点的深度。

public interface IComponent {

    void sayHello(int deep);

    void add(IComponent component);

    void remove(IComponent component);

    IComponent getChild(int i);
}

叶子节点,不允许有下级节点。所以子节点增删改查的方法要么不实现,要么直接抛出异常。

public class Leaf implements IComponent {

    public void sayHello(int deep) {
        for (int i = 0; i < deep; i++) {
            System.out.print("-");
        }
        System.out.println("leaf hello");
    }

    public void add(IComponent component) {
    }

    public void remove(IComponent component) {
    }

    public IComponent getChild(int i) {
        return null;
    }
}

容器节点,维持对子节点列表的引用。

public class Composite implements IComponent {

    private List components = new ArrayList();

    public void sayHello(int deep) {
        for (int i = 0; i < deep; i++) {
            System.out.print("-");
        }
        System.out.println("composite hello.");
        deep++;
        for (IComponent component : components) {
            component.sayHello(deep);
        }
    }

    public void add(IComponent component) {
        components.add(component);
    }

    public void remove(IComponent component) {
        components.remove(component);
    }

    public IComponent getChild(int i) {
        return components.get(i);
    }
}

执行上面的例子。这里地方随意建立一棵树

public class TestComposite {

    public static void main(String[] args) {

        // 建立树
        IComponent root = new Composite();

        IComponent secondNode1 = new Composite();
        root.add(secondNode1);

        IComponent thirdNode = new Composite();
        thirdNode.add(new Leaf());
        thirdNode.add(new Leaf());
        secondNode1.add(thirdNode);
        secondNode1.add(new Leaf());
        secondNode1.add(new Leaf());

        IComponent secondNode2 = new Composite();
        secondNode2.add(new Leaf());
        root.add(secondNode2);

        root.add(new Leaf());
        root.add(new Leaf());
        root.add(new Leaf());


        // 执行
        root.sayHello(0);
    }
}

输出如下:

composite hello.
-composite hello.
--composite hello.
---leaf hello
---leaf hello
--leaf hello
--leaf hello
-composite hello.
--leaf hello
-leaf hello
-leaf hello
-leaf hello

统一的接口,让操作变得容易。

3. 应用

应用场景:

  • 需要建立层次结构,区分整体和部分,提供有一致的接口。
  • 需要建立对象树。
  • 需要区分叶子和容器。

3.1. MyBatis:Plugin

3.2. Android:View 树

Android 系统中所有的 UI 都是基于 View 和 ViewGroup 创建的。

View 代表界面的一块矩形区域,可绘制,可响应交互事件。

ViewGroup 也是 View,同时还是 View 的容器。

然后 View 和 ViewGroup 的实现类,以树形结构组合在一起,创建复杂的手机页面。

Android 的 View 树是组合模式的典型应用。

组合模式——对象树的实现_第3张图片

实际应用一般不会直接使用 View 和 ViewGroup,而是使用它们的子类。

比如 ViewGroup 的重要子类有:

  • FrameLayout,帧布局。
  • RelativeLayout,相对布局。
  • LinnearLayout,线性布局。
  • ConstraintLayout,约束布局。
  • RecyclerView,列表。

等等,或者由应用者自定义容器。

View 的一些重要子类有:

  • TextView,文本框。
  • ImageView,图片控件。
  • EditText,编辑框。

通过组合模式,把这一系列的 ViewGroup 和 View 组装成一棵树。很多重要的 UI 流程就是基于这棵树进行递归调用实现的。

  • View 的计算,measure 过程。
  • View 的布局,layout 过程。
  • View 的绘制,draw 过程。
  • 事件的传递分发。其中事件的处理过程采用的是责任链的方式。

4. 特点

4.1. 优势

  • 屏蔽层次结构,客户端把精力放在节点对象的处理,忽略层次的差异。
  • 简化代码,容器和叶子都视为抽象构件的具体实现,使用一致的接口访问。
  • 易修改和扩展,新增容器和叶子无需对类库进行修改。
  • 树的解决方案,组合模式可以通过递归操作进行建树。

4.2. 缺点

  • 设计复杂,需要理解和理清层次关系。

你可能感兴趣的:(设计模式,设计模式大全)