组合模式(Composite)

定义

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

本质

统一叶子对象和组合对象

登场角色

  • Leaf(叶子)

    表示“内容”的角色,该角色中不能放入其他角色。

  • Composite(复合物)

    表示“容器”的角色,可以在其中放入Leaf角色和Composite角色。

  • Component

    使Leaf角色和Composite角色觉有一致性的角色,是叶子角色和复合物角色的父类。

  • Client

    使用组合模式的角色。

示例代码

/**
 * 表示文件和文件夹的抽象类
 *
 * 叶子角色和复合物角色的父类
 */
public abstract class Dir {
    //声明一个List元素存储文件夹下的所有元素
    protected List<Dir> dirs = new ArrayList<>();
    private String name;//当前文件或者文件夹的名称
    public Dir(String name) {
        this.name = name;
    }
    //添加一个文件或者文件夹
    public abstract void addDir(Dir dir);
    //移除一个文件或者文件夹
    public abstract void removeDir(Dir dir);
    //清除文件夹下的所有元素
    public abstract void clear();
    //输入文件夹目录结构
    public abstract void print();
    //获取文件夹下所有的文件或者文件夹
    public abstract List<Dir> getFiles();
    //获取文件或者文件夹的名称
    
    public String getName() {
        return name;
    }
}


/**
 * 叶子角色
 */
public class File extends Dir{
    public File(String name) {
        super(name);
    }
    @Override
    public void addDir(Dir dir) {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }
    @Override
    public void removeDir(Dir dir) {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }
    @Override
    public void clear() {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }
    @Override
    public void print() {
        System.out.print(getName());
    }
    @Override
    public List<Dir> getFiles() {
        throw new UnsupportedOperationException("文件对象不支持该操作");
    }
}



/**
 * 复合角色
 */
public class Folder extends Dir{
    public Folder(String name) {
        super(name);
    }
    @Override
    public void addDir(Dir dir) {
        dirs.add(dir);
    }
    @Override
    public void removeDir(Dir dir) {
        dirs.remove(dir);
    }
    @Override
    public void clear() {
        dirs.clear();
    }
    @Override
    public void print() {
        System.out.print(getName() + "(");
        Iterator<Dir> iterator = dirs.iterator();
        while (iterator.hasNext()){
            Dir dir = iterator.next();
            dir.print();
            if(iterator.hasNext()){
                System.out.print(",");
            }
        }
        System.out.print(")");
    }
    @Override
    public List<Dir> getFiles() {
        return dirs;
    }
}



/**
 * 测试,使用组合模式的角色
 */
public class Client {
    public static void main(String[] args){
        //构造一个目录对象表示C盘根目录
        Dir diskC = new Folder("C盘");
        //C盘根目录下有一个文件
        diskC.addDir(new File("hello.txt"));
        //C盘根目录下还有三个子目录
        Dir windows = new Folder("Windows");
        diskC.addDir(windows);
        Dir logs = new Folder("Logs");
        diskC.addDir(logs);
        Dir users = new Folder("users");
        diskC.addDir(users);
        ///Windows目录下添加文件
        windows.addDir(new File("windows.txt"));
        //Logs目录下添加文件
        logs.addDir(new File("logs.txt"));
        //Users目录下添加文件
        users.addDir(new File("users.txt"));
        
        diskC.print();
    }
}

运行结果

C盘(hello.txt,Windows(windows.txt),Logs(logs.txt),users(users.txt))

功能

可以让使用者不用在区分叶子对象和组合对象,而是以一个统一的方式来调用。

优点

  • 定义了包含基本对象和组合对象的类层次结构
  • 统一了组合对象和叶子对象
  • 简化了使用者的调用
  • 更容易扩展,新定义的叶子对象和复合对象可以很容易的与已有结构兼容,而使用者不需要为了添加新的对象而改变。

缺点

很难限制组件中的组件类型。

何时使用

  • 表示对象的“对象-整体”层次结构。
  • 从一整体中能够独立出部分模块或者功能的场景。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。