图解设计模式--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 模式。

你可能感兴趣的:(图解设计模式--Composite(组合)模式)