设计模式-组合模式

组合模式使用场景

把部分和整体的关系用树形结构来表示,从而使客户端可以使用统一的方式处理部分对象和整体对象

组合模式核心

  • 抽象构件角色(Component):定义了叶子和容器构件的共同点
  • 叶子(Leaf)构件角色:无子节点
  • 容器(Composite)构件角色:有容器特征,可以包含子节点

UML

这里写图片描述

说明

举个简单的例子,就像我们windows系统的文件系统一样,比如说一个文本,一个视频,一个音频文件都是Leaf,像是文件夹,都是Composite。

不知道大家有没有注意到,他们都有一个核心的方法,operation,这个方法,是这个模式的核心思想,也就是说,实现了这些接口的类,都可以使用相同的处理方法,比如说我们在做一个系统,有一个树形的目录结构,那么在使用的时候并不是每个人都能够看到所有的节点的,那么如何来判断这些树形结构是否可见呢,就可以使用这种方式来判断,因为不管是哪一层的节点,都需要判断权限,所有的文件夹,不同的文件类型,都需要实现这个方法。

Composite中的一些add,remove,get方法可以理解为文件夹,可以增加文件,删除文件,获取文件等。

上面的内容都是使用理论的方式来介绍组合模式,不太直观,下面我们就给出代码实现。

代码实现

AbstractFile.java

public interface AbstractFile {

    void hasAuth();

}

这个类相当于之前UML中的Component,他是所有文件和文件夹的接口,定义了判断权限的方法。

ImageFile.java

public class ImageFile implements AbstractFile {

    private String name;

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

    @Override
    public void hasAuth() {
        System.out.println("----图像文件:" + name + "判断是否有权限");
    }

}

上面的类相当于叶子节点,因为他们代表的是具体的文件,图片文件还有类似的定义,如文本文件,视频文件等等。

TestFile.java

public class TestFile implements AbstractFile {

    private String name;

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

    @Override
    public void hasAuth() {
        System.out.println("----文本文件:" + name + "判断是否有权限");
    }

}

VideoFile.java

public class VideoFile implements AbstractFile {

    private String name;

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

    @Override
    public void hasAuth() {
        System.out.println("----视频文件:" + name + "判断是否有权限");
    }

}

这些类都相当于是叶子节点了。说完叶子节点,还有一类是父节点,也就是文件夹。
Folder.java

public class Folder implements AbstractFile {

    private String name;

    private List<AbstractFile> list = new ArrayList<>();

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

    public void add(AbstractFile file) {
        list.add(file);
    }

    public void remove(AbstractFile file) {
        list.remove(file);
    }

    public AbstractFile getChild(int index) {
        return list.get(index);
    }

    @Override
    public void hasAuth() {
        System.out.println("----文件夹:" + name + "判断是否有权限");
        for(AbstractFile abstractFile : list){
            abstractFile.hasAuth();
        }
    }
}

其中有一些增删改查的方法,其实很简单,都是针对list的。
最后在验证权限的时候,其实是递归调用的,子文件夹还会继续递归调用,知道都是叶子节点为止。
下面进行测试:
Client.java

public class Client {

    public static void main(String[] args) {
        AbstractFile f2, f3, f4;
        Folder f1 = new Folder("我的电脑");
        f2 = new ImageFile("hello.jpg");
        f3 = new TestFile("test.txt");
        f4 = new TestFile("人民的名义.mp4");

        f1.add(f2);
        f1.add(f3);
        f1.add(f4);

        f1.hasAuth();
    }

}

输出结果如下:

—-文件夹:我的电脑判断是否有权限
—-图像文件:hello.jpg判断是否有权限
—-文本文件:test.txt判断是否有权限
—-文本文件:人民的名义.mp4判断是否有权限

这里可以看到,我只是判断了文件夹的权限,但是文件的权限也都判断了,如果在我的电脑下还有文件夹,那么也都会一起判断,这里就不一一介绍了。

总结:组合模式可以将整体和部分都使用统一的方式去处理,而且天然的实现了递归。

应用场景:

  • 操作系统的资源管理器
  • GUI的容器层次图
  • XML文件解析
  • HTML的解析
  • OA系统组织结构的处理
  • Junit单元测试框架
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值