[设计模式] 结构型:组合模式(Composite Pattern)

什么是组合模式

组合模式也叫合成模式,是将含有父子关系的一组单个对象,组合成用树结构表示的对象,也就是组合对象,可以表达出局部与整体的层次关系。

组合对象具有树结构的特性,所以,针对单个对象和组合对象的操作,就能抽象出统一的过程。

说白了,这也是树的自身特性,整体是树结构,局部也是树结构,能对树进行的操作,既适用于整体数据,也适用于局部数据。

通俗理解,组合模式就是实现对树结构的操作,要点有两个:

  1. 将具有父子关系的对象合成树结构,就是组合对象
  2. 用抽象、封装的编程思想实现对树结构的操作,适用于局部,也要适用于整体

设计与实现

提到树结构,就必须要注意树的几个节点类型:

  1. 树根结点:最顶层的节点,没有父节点,只有子节点
  2. 树枝节点:中间节点,有父节点,也有子节点
  3. 树叶节点:最底层节点,只有父节点,没有子节点

树结构在计算机中的应用,最典型的两个业务场景就是“文件目录”和“树型菜单”。

就拿文件目录举例子,看编程如何实现树结构的操作。

树根结点就是唯一的根目录,树枝节点就是中间的各级目录,树叶节点就是每级目录下的各个文件。

在下面的代码中,简化了实际场景中文件目录的功能及其表现,只提供构造树结构的方法,以及列举出目录及其子目录下所有文件的方法。

// 树节点的统一抽象
public abstract class TreeNode {
    protected String name;

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

// 树根节点(根目录)、树枝节点(一般目录)的统一抽象
public class Branch extends TreeNode {
    private List<TreeNode> list = new ArrayList<>();

    public Branch(String name) {
        super(name);
    }

    public void add(TreeNode... nodes) {
        for (TreeNode node : nodes) list.add(node);
    }

    public void fileList() {
        fileList("");
    }

    private void fileList(String prefix) {
        for (TreeNode treeNode : list) {
            if (treeNode instanceof Branch) {
                Branch branch = (Branch) treeNode;
                branch.fileList(prefix + branch.name + "/");
            } else {
                System.out.println(prefix + treeNode.name);
            }
        }
    }
}

// 树叶节点(文件)
public class Leaf extends TreeNode {
    private String content;

    public Leaf(String name, String content) {
        super(name);
        this.content = content;
    }
}

这就是针对文件目录的组合模式代码实现,只实现了必要的属性方法,省略了很多不必要的代码。

提供一个简单的测试方法,Branch对象的fileList()方法既适用于整体的组合对象,也适用于局部的对象:

public static void main(String[] args) {
    Branch root = new Branch("/");
    Branch dir1 = new Branch("dir1");
    Leaf dir1File1 = new Leaf("file1", "dir1 file1 content");
    dir1.add(dir1File1);
    Branch dir2 = new Branch("dir2");
    Leaf dir2File1 = new Leaf("file1", "dir2 file1 content");
    Leaf dir2File2 = new Leaf("file2", "dir2 file2 content");
    dir2.add(dir2File1, dir2File2);
    Branch dir3 = new Branch("dir3");
    Leaf dir3File1 = new Leaf("file1", "dir3 file1 content");
    Leaf dir3File2 = new Leaf("file2", "dir3 file2 content");
    Leaf dir3File3 = new Leaf("file3", "dir3 file3 content");
    dir3.add(dir3File1, dir3File2, dir3File3);
    root.add(dir1, dir2, dir3);
    System.out.println("------/目录及其子目录文件列表------");
    root.fileList();
    System.out.println("------dir1目录及其子目录文件列表------");
    dir1.fileList();
    System.out.println("------dir2目录及其子目录文件列表------");
    dir2.fileList();
    System.out.println("------dir3目录及其子目录文件列表------");
    dir3.fileList();
}

组合模式的注意事项

可以说,组合模式就是树型结构的一种编程方法,如果应用场景很符合树结构的特征,那么,使用组合模式可以起到很好的作用。

但是,与此同时,树型结构的特征也在某种程度上限制了应用场景,如果应用场景在今后的变化中,脱离了树结构,或者不完全是树结构的表现,那么,组合模式就很难升级扩展。

综合而言,组合模式是个比较特殊的设计模式,与树型结构强相关,使用前,一定要多考虑当前以及今后的应用场景,是否真的契合树型结构条件。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值