介绍

组合模式(Composite Pattern)是一种结构型设计模式,它使你能够将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

1.定义


组合模式允许将叶子对象和组合对象(容器对象)统一处理。

2. 主要作用


  • 简化客户端代码:客户端可以使用相同的方式处理单个对象和组合对象,减少了代码复杂度。
  • 构建树形结构:能够轻松地创建和管理复杂的树形结构。
  • 便于扩展:新增的叶子对象或组合对象不需要修改现有代码。

3. 解决的问题


  • 在需要处理树形结构时,直接使用传统的对象管理会导致复杂性和不一致性。
  • 组合模式提供了一种方式,使得叶子节点和组合节点都实现相同的接口,从而提供了一种一致的调用方式。

4. 模式原理


包含角色:

  • Component(组件):定义了组合对象和叶子对象的共同接口,可以包含一些默认的行为。
  • Leaf(叶子节点):叶子节点,只实现了Component接口的行为,不包含其他子节点。
  • Composite(组合节点):组合节点,实现了Component接口,并且包含子节点的管理功能,比如添加、删除和遍历子节点。

UML类图:

技术成神之路:设计模式(十七)组合模式_子节点

简单示例:

// Component
interface FileSystemComponent {
    void showDetails();
}

// Leaf
class File implements FileSystemComponent {
    private String name;

    public File(String name) {
        this.name = name;
    }

    @Override
    public void showDetails() {
        System.out.println("File: " + name);
    }
}

// Composite
class Folder implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> components = new ArrayList<>();

    public Folder(String name) {
        this.name = name;
    }

    public void addComponent(FileSystemComponent component) {
        components.add(component);
    }

    public void removeComponent(FileSystemComponent component) {
        components.remove(component);
    }

    @Override
    public void showDetails() {
        System.out.println("Folder: " + name);
        for (FileSystemComponent component : components) {
            component.showDetails();
        }
    }
}

调用

public class CompositePatternDemo {
    public static void main(String[] args) {
        FileSystemComponent file1 = new File("File1.txt");
        FileSystemComponent file2 = new File("File2.txt");

        Folder folder = new Folder("MyFolder");
        folder.addComponent(file1);
        folder.addComponent(file2);

        folder.showDetails();
    }
}

打印输出

Folder: MyFolder
File: File1.txt
File: File2.txt

到这里,不知道你是不是有和我同样的疑问,在Java中 File 是不是实现了组合模式?

File类中,文件和目录(文件夹)之间的关系可以被看作是组合模式的体现。一个File对象可以表示一个文件,也可以表示一个目录。目录可以包含多个File对象(文件和子目录),形成树状结构,而且他们都有统一的方法 listFiles()delete()renameTo()等。这意味着,无论你在操作文件还是目录,都可以通过相同的方法来进行操作,这体现了组合模式的核心思想。BUTFile 类本身并没有直接实现组合模式,可以被视为一种组合模式的应用,并非严格意义上的组合模式。 类似的还有 Java 的集合框架中,java.util.Listjava.util.Set 等接口的实现类如 ArrayListHashSet等。

那么,在SDK中有没有典型的组合模式实例?答案是肯定的。

在 Android 中,View 是所有 UI 组件的基类,而 ViewGroup 是一个特殊的 View,它可以包含其他 View

Component(组件)View 是基本组件,代表 UI 中的一个元素。 Leaf(叶子节点)View 又代表叶子节点,因为它们不包含子视图。 Composite(组合节点)ViewGroup 代表组合节点,可以包含多个 View 或其他 ViewGroup

这样就可以统一创建和管理复杂的用户界面了。

5. 优缺点


优点:

  1. 客户端可以以一致的方式处理单个对象和组合对象。
  2. 增加新组件时,系统的扩展性良好。

缺点:

  1. 设计复杂性增加,因为需要定义一个接口或抽象类。
  2. 不适合过于复杂的树形结构。

6. 应用场景


  • 想表示对象的部分-整体层次结构。
  • 希望用户忽略组合对象和单个对象的不同,用户将统一地使用组合结构中的所有对象。

7. 总结


组合模式是一种强大的设计模式,适用于处理树形结构中的对象关系。通过将对象组合成树形结构,组合模式使得客户端可以统一地处理单个对象和组合对象,从而简化了代码逻辑和结构。然而,组合模式也增加了类的复杂性,需要在设计时权衡其优缺点。