一、定义
GOF中对Composite模式这样描述:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
组合涉及的是一组对象,其中有的对象可能包含有其他的对象,因此,有的对象可能代表一个对象群组,而有的则是单个对象。组合模式包括两个重要的建模概念:1.所设计的群组既要能包含单个个体,又要能包含其他群组。数据结构很自然的有递归特性。2.定义出单个对象和对象群组的公共特性(接口)。将公共接口提供给用户,用户可以用统一的接口处理单个对象以及组合对象。这里体现了面向对象设计的一个原则:将变化的与不变的分离开来。
二、场景设计
符合组合模式的典型例子就是文件系统的目录树结构。这里以Hadoop的HDFS文件系统为例,单个文件和文件目录分别用INodeFile和INodeDirectory来描述。每个INodeDirectory中可能还包含多个INodeFile和INodeDirectory。在INodeFile和INodeDirectory的上层,还有一个INode 抽象类,其中抽象了INodeFile和INodeDirectory的公共接口和属性。
三、类结构图
用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶节点,则直接处理请求。如果接受者是一个Composite,则通常将请求转发给他的子部件,在转发请求之前或之后可能要执行一些辅助操作。
四、代码示例
INode.java
public interface INode {
int getFileNum();
void Add(INode node);
void Remove(INode node);
void OutputInfo();
}
INodeFile.java
public class INodeFile implements INode {
String name;
INodeFile(String name)
{
this.name=name;
}
@Override
public int getFileNum() {
// TODO Auto-generated method stub
return 1;
}
@Override
public void Add(INode node) {
// TODO Auto-generated method stub
System.out.println("File-----No subdirectory");
}
@Override
public void Remove(INode node) {
// TODO Auto-generated method stub
System.out.println("File-----No subdirectory");
}
@Override
public void OutputInfo() {
// TODO Auto-generated method stub
System.out.print("file: "+name+"|");
}
}
INodeDirectory.java
import java.util.*;
public class INodeDirectory implements INode {
private LinkedList<INode> list;
String name;
INodeDirectory(String name)
{
this.name=name;
list=new LinkedList<INode>();
}
@Override
public int getFileNum() {
// TODO Auto-generated method stub
int sum=0;
for(INode temp:list)
{
sum+=temp.getFileNum();
}
return sum;
}
@Override
public void Add(INode node) {
// TODO Auto-generated method stub
list.add(node);
}
@Override
public void Remove(INode node) {
// TODO Auto-generated method stub
list.remove(node);
}
@Override
public void OutputInfo() {
// TODO Auto-generated method stub
System.out.print("directory: "+name+"|");
int i=0;
for(INode temp:list)
{
temp.OutputInfo();
}
System.out.println("");
}
}
Client.java
public class Client {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
INode plant=new INodeDirectory("plant");
INode root=new INodeDirectory("root");
INode music=new INodeFile("music");
INode pdf=new INodeFile("pdf");
INode movie=new INodeFile("movie");
plant.Add(music);
plant.Add(pdf);
plant.Add(movie);
INode book=new INodeFile("book");
root.Add(plant);
root.Add(book);
System.out.println(root.getFileNum());
root.OutputInfo();
}
}
运行结果:
4
directory: root|directory: plant|file: music|file: pdf|file: movie|
file: book|