学习设计模式之组合模式

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

类结构图
在这里插入图片描述
Component
组合中的对象声明接口,在适当情况下,实现所有类共有的接口默认行为。声明一个接口用于访问和管理 Component 的子部件。
Composite
定义节点的行为,用来存储子部件,在 Component 接口中实现与子部件有关的操作,比如增加 add 和删除 remove。
Leaf
在组合中表示叶节点对象,叶节点没有子节点。

树结构的例子有很多,文件、公司、菜单的结构。下面我们就用文件的例子来看看。

代码实现

public interface IFile {
    void delete();

    String getName();

    void newFile(String name);

    void delFile(String name);

    IFile getFile(int index);
}

public class Folder implements IFile {

    private String name;
    private IFile folder;
    private List<IFile> files;

    public Folder(String name) {
        this(name, null);
    }

    public Folder(String name, IFile folder) {
        this.name = name;
        this.folder = folder;
        files = new ArrayList<>();
    }

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void delete() {
        Iterator<IFile> iterator = files.iterator();
        while (iterator.hasNext()) {
            iterator.remove();
        }
        System.out.println(">>>>>>>> 删除子文件结束 <<<<<<<<<<");
        if (null != this.folder) {
            this.folder.delFile(this.name);
        }
        System.out.println(">>>>>>>> 删除 " + this.name + " 结束 <<<<<<<<<<");
    }

    @Override
    public void newFile(String name) {
        if (name.contains(".")) {
            files.add(new File(name, this));
        } else {
            files.add(new Folder(name, this));
        }
    }

    @Override
    public void delFile(String name) {
        Iterator<IFile> iterator = files.iterator();
        while (iterator.hasNext()) {
            IFile file = iterator.next();
            if (file.getName().equals(name)) {
                iterator.remove();
            }
        }
    }

    @Override
    public IFile getFile(int index) {
        return this.files.get(index);
    }
}

public class File implements IFile {

    private String name;
    private IFile folder;

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

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void delete() {
        this.folder.delFile(this.name);
        System.out.println(">>>>>>>>>> 删除 " + this.name + " <<<<<<<<<<");
    }

    @Override
    public void newFile(String name) {
        System.out.println(">>>>>>>>>> 不支持创建新文件 <<<<<<<<<<");
    }

    @Override
    public void delFile(String name) {
        System.out.println(">>>>>>>>>> 不支持删除子文件 <<<<<<<<<<");
    }

    @Override
    public IFile getFile(int index) {
        System.out.println(">>>>>>>>>> 不支持获取子文件 <<<<<<<<<<");
        return null;
    }
}

客户端示例

public class Client {
    public static void main(String[] args) {
        IFile root = new Folder("root 文件");
        root.newFile("1 文件");
        root.newFile("2 文件");
        root.newFile("3 文件");

        IFile c = root.getFile(0);
        c.newFile("Program Files");
        IFile program = c.getFile(0);
        program.newFile("怎么学习设计模式.pdf");

        IFile d = root.getFile(1);
        d.newFile("学习学籍");
        IFile pdfs = d.getFile(0);
        pdfs.newFile("agile java.pdf");
        pdfs.newFile("Effective Java 中文第二版.pdf");
        pdfs.newFile("Java8实战.pdf");

        showFiles(root);
    }

    private static final void showFiles(IFile iFile) {
        showFiles(null, iFile);
    }

    private static final void showFiles(String prefix, IFile iFile) {
        if (null == prefix) {
            prefix = "";
        }
        System.out.println(prefix + iFile.getName());
        if (iFile instanceof Folder) {
            for (int i = 0; ; i++) {
                try {
                    if (iFile.getFile(i) != null) {
                        showFiles(prefix + "--", iFile.getFile(i));
                    }
                } catch (Exception e) {
                    break;
                }
            }
        }
    }
}

运行结果

root 文件
--1 文件
----Program Files
------怎么学习设计模式.pdf
--2 文件
----学习学籍
------agile java.pdf
------Effective Java 中文第二版.pdf
------Java8实战.pdf
--3 文件

Process finished with exit code 0

使用场景
当发现需求中是体现部分与整体层级的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用结构中的所有对象时,就应该考虑使用组合模式了。

优点

  1. 组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
  2. 将”客户代码与复杂的对象容器结构“解耦。
  3. 可以更容易地往组合对象中加入新的构件。

缺点

使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。

猜你喜欢

转载自blog.csdn.net/qq_16830879/article/details/88077013