》》能够使容器与内容具有一致性,创造出递归结构的模式就是Composite 模式。
-----------以下示例程序的功能是列出文件和文件夹的一览。
》》示例程序的类图:
------------------------
《Entry 类》
package composite;
/*
* 抽象类,用来实现 File 类和 Directory 类的一致性
*/
public abstract class Entry {
public abstract String getName(); //获取名字
public abstract int getSize(); //获取大小
//加入目录条目,并且抛出了FileTreatmentException异常
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()+")";
}
}
-------------------------------------
《File 类》
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);
}
}
----------------------------
《Directory 类》
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 Entry add(Entry entry){ //增加目录条目
directory.add(entry);
return this;
}
public int getSize(){ //获取大小
int size = 0;
//遍历集合
Iterator it = directory.iterator();
while(it.hasNext()){
Entry entry = (Entry)it.next();
size += entry.getSize();
}
return size;
}
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);
}
}
}
------------------------------
《FileTreatmentException类》------》自定义处理异常
package composite;
public class FileTreatmentException extends RuntimeException{
public FileTreatmentException(){
}
public FileTreatmentException(String msg){
super(msg);
}
}
-------------------------------
《Main 类》-----测试程序
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("hanakpo");
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();
}
}
}
-----------------------------------------------------------
《以上示例的文件结构》
-----root
------bin
----vi
----latex
------tmp
------usr
----yuki
----diary.html
----Composite.java
----hanako
----memo.tex
----tomura
----game.doc
----junk.mail
--------------------------------------------------------
《运行结果》
Making root entries...
/root(30000)
/root/bin(30000)
/root/bin/vi(10000)
/root/bin/latex(20000)
/root/tmp(0)
/root/usr(0)
Making user entries...
/root(31500)
/root/bin(30000)
/root/bin/vi(10000)
/root/bin/latex(20000)
/root/tmp(0)
/root/usr(1500)
/root/usr/yuki(300)
/root/usr/yuki/diary.html(100)
/root/usr/yuki/Composite.java(200)
/root/usr/hanakpo(300)
/root/usr/hanakpo/memo.tex(300)
/root/usr/tomura(900)
/root/usr/tomura/game.doc(400)
/root/usr/tomura/junk.mail(500)
----------------------------------------------
《Composite模式中的登场角色》
*****Leaf(树叶)
表示“内容”的角色。在该角色中不能放入其他对象。在示例程序中,由 File 扮演此角色。
*****Composite(复合物)
表示容器的角色。可以在其中放入 Leaf 角色 和 Composite 角色。在示例程序中,
Directory 类扮演此角色。
*****Component
使 Leaf 角色和 Composite 角色具有 一致性的角色。Component 角色是 Leaf 角色和
Composite 角色的父类。在示例程序中,由 Entry 类扮演此角色。
***** Client
使用 Composite 模式的角色。在示例程序中,Main 类扮演此角色。
--------------------------------------------------
《扩展思路的要点》
1.多个和单个的一致性
使用Composite 模式可以使容器与内容具有一致性,也可以称其为多个和单个的一致性,
即将多个对象结合在一起,当作一个对象进行处理。
2.Add 方法应该放在哪里
(1)、定义在 Entry 类中,报错
(2)、定义在 Entry 类中,但什么都不做
(3)、声明在Entry 类中,但不实现(该add 方法为抽象方法)
(4)、只定义在 Directory 类中
3.到处都是递归结构
例如:在视窗系统中,一个窗口可以含有一个子窗口,这就是 Composite 模式的典型应用。
在文章的列表中,各列表之间可以相互嵌套,这也是一种递归。
通常来说,树结构的数据结构都适用 Composite 模式。
--------------------------------------------------
相关的设计模式
1.Command 模式
2.Visitor模式
3.Decorator 模式