图解设计模式--Composite(组合)模式

容器与内容的一致性

Composite 模式

能够使容器与内容具有一致性,创造出递归结构的模式。

示例程序

名字 说明 角色
Entry 抽象类,用来实现 File 类和 Directory 类的一致性 Component
File 表示文件的类 Leaf
Directory 表示文件夹的类 Composite
FileTreatmentException 表示向文件夹增加 Entry 时发生的异常的类
Main 测试程序行为的类 Client

Entry.java

package composite;

public abstract class Entry {

    public abstract String getName();
    public abstract int getSize();
    public Entry add(Entry entry) throws FileTreatmentException {
        throw new FileTreatmentException();
    }
    public void printList() {
        printList("");
    }
    protected abstract void printList(String prefix);

    public String toString() {
        return getName() + "(" + getSize() + ")";
    }

}

Directory.java

package composite;

import java.util.ArrayList;
import java.util.Iterator;

public class Directory extends Entry{
    private String name;
    private ArrayList directory = new ArrayList();
    public Directory(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        int size = 0;
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry) it.next();
            size += entry.getSize();
        }
        return size;
    }
    public Entry add(Entry entry) {
        directory.add(entry);
        return this;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
        Iterator it = directory.iterator();
        while (it.hasNext()) {
            Entry entry = (Entry)it.next();
            entry.printList(prefix + "/" + name);
        }
    }
}

File.java

package composite;

public class File extends Entry {
    private String name;
    private int size;
    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }
    public String getName() {
        return name;
    }
    public int getSize() {
        return size;
    }
    protected void printList(String prefix) {
        System.out.println(prefix + "/" + this);
    }
}

FileTreatmentException.java

package composite;

public class FileTreatmentException extends RuntimeException {
    public FileTreatmentException(){}
    public FileTreatmentException(String msg){
        super(msg);
    }
}

Main.java

package composite;

public class Main {
    public static void main(String[] args) {
        try {
            System.out.println("Making root entries...");
            Directory rootdir = new Directory("root");
            Directory bindir = new Directory("bin");
            Directory tmpdir = new Directory("tmp");
            Directory usrdir = new Directory("usr");
            rootdir.add(bindir);
            rootdir.add(tmpdir);
            rootdir.add(usrdir);
            bindir.add(new File("vi", 10000));
            bindir.add(new File("latex", 20000));
            rootdir.printList();

            System.out.println("");
            System.out.println("Making user entries...");
            Directory yuki = new Directory("yuki");
            Directory hanako = new Directory("hanako");
            Directory tomura = new Directory("tomura");
            usrdir.add(yuki);
            usrdir.add(hanako);
            usrdir.add(tomura);
            yuki.add(new File("diary.html", 100));
            yuki.add(new File("Composite.java", 200));
            hanako.add(new File("memo.tex", 300));
            tomura.add(new File("game.doc", 400));
            tomura.add(new File("junk.mail", 500));

            rootdir.printList();
        } catch (FileTreatmentException e) {
            e.printStackTrace();
        }
    }
}

Composite 模式中的角色

  1. Leaf(树叶)

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

  2. Composite(组合)

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

  3. Component(组件)

    使 Leaf 角色和 Composite 角色具有一致性的角色。是Leaf、Composite的父亲。

  4. Client

    使用 Composite 模式的角色。

拓展思路

一、Add 方法应该放在哪里?

  1. 定义在 Entry 类中,报错
  2. 定义在 Entry 类中,但什么都不做
  3. 定义在 Entry 类中,但不实现
  4. 只定义在 Directory 类中

二、通常来说,树结构的数据结构都适用 Composite 模式。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1 场景问题# 1.1 商品类别树## 考虑这样一个实际的应用:管理商品类别树。 在实现跟商品有关的应用系统的时候...
    七寸知架构阅读 6,073评论 10 59
  • 引入composite模式 composite模式的实例 composite模式的分析 小结 引入composit...
    六尺帐篷阅读 16,155评论 1 13
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,765评论 18 399
  • 想和你去100个城市.来99个拥抱.看98场日落.要97次接吻.拍96张照片.买95朵玫瑰.去94家餐馆.看93次...
    onlooker纳木错阅读 272评论 0 1
  • 万病之源源于血液不干净 血液可以运输氧气,营养,荷尔蒙,热量,免疫球蛋白(灰指甲,脚气,湿疹),废物(老年斑,痤疮)
    阿果的幸运阅读 138评论 0 0