1、组合模式
Composite模式也叫做组合模式,是构造型的设计模式之一。通过递归手段来构造树形的对象结构,并可以通过一个对象来访问整个对象树。
组合模式有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。2、结构图
组合模式的精髓是组合,结构图示如下:
3、角色
组合模式中,主要有如下的三种角色对象,在上面的结构图示中已经展示过了,这里再简单说明一下:
Component(树形结构的节点抽象)1)为所有的对象定义统一的接口(公共的属性,行为等的定义)
2)提供管理子节点对象的接口方法
3)提供管理父节点对象的接口方法
Leaf(树形结构的叶子节点):Component的实现子类
Composite(树形结构的枝节点):Component的实现子类
4、源码示例
一个文件与文件夹的父类节点,源码:
import java.util.ArrayList;
import java.util.List;
/**
* 文件节点的抽象(文件或者文件夹的父类)
* @author ljtyzhr
*
*/
public interface RootFile {
/**
* 显示名称
*/
public void displayName();
/**
* 添加文件
* @return
*/
public boolean addFile(RootFile rootFile);
/**
* 移除文件
* @return
*/
public boolean removeFile(RootFile rootFile);
/**
* 获得子节点
* @return
*/
public ArrayList<RootFile> getChild();
}
文件列表节点,如下:
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的文件
* @author ljtyzhr
*
*/
public class MyFile implements RootFile {
private String fileName ;
public MyFile(String fileName) {
// TODO Auto-generated constructor stub
this.fileName = fileName;
}
@Override
public void displayName() {
// TODO Auto-generated method stub
System.out.println(fileName);
}
@Override
public boolean addFile(RootFile rootFile) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean removeFile(RootFile rootFile) {
// TODO Auto-generated method stub
return false;
}
@Override
public ArrayList<RootFile> getChild() {
// TODO Auto-generated method stub
return null;
}
}
文件夹节点,源码如下:
import java.util.ArrayList;
import java.util.List;
/**
* 自定义的文件夹名称
*
* @author ljtyzhr
*
*/
public class MyFolder implements RootFile {
private String folderName ;
private ArrayList<RootFile> children;
public MyFolder(String folderName) {
// TODO Auto-generated constructor stub
this.folderName = folderName;
children = new ArrayList<RootFile>();
}
@Override
public void displayName() {
// TODO Auto-generated method stub
System.out.println(folderName);
}
@Override
public boolean addFile(RootFile rootFile) {
// TODO Auto-generated method stub
return children.add(rootFile);
}
@Override
public boolean removeFile(RootFile rootFile) {
// TODO Auto-generated method stub
return children.remove(rootFile);
}
@Override
public ArrayList<RootFile> getChild() {
// TODO Auto-generated method stub
return children;
}
}
测试案例:
import java.util.ArrayList;
public class MainClass {
public static void main(String[] args) {
MyFolder folder = new MyFolder("D:");
// 游戏目录
MyFolder game = new MyFolder("game");
MyFile readme = new MyFile("readme.txt");
// 娱乐
MyFolder fun = new MyFolder("fun");
MyFile fun_file = new MyFile("fun_file.txt");
fun.addFile(fun_file);
game.addFile(fun);
folder.addFile(game);
folder.addFile(readme);
displayTree(folder,0);
}
public static void displayTree(RootFile rootFile,int deep){
for (int i = 0; i < deep; i++) {
System.out.print("===");
}
// 显示自己
rootFile.displayName();
// 获得子结点
ArrayList<RootFile> list = rootFile.getChild();
// 进行判断
for (RootFile root : list) {
// 如果是一个文件,就直接显示文件名,否则就递归
if (root instanceof MyFile) {
for (int i = 0; i <= deep; i++) {
System.out.print("===");
}
root.displayName();
} else {
displayTree(root,deep+1);
}
}
}
}
5、结果分析
结果如下:
D:
===game
======fun
=========fun_file.txt
===readme.txt
分析:
D盘下面有两个文件,game文件夹和readme.txt文件,game文件夹下面有fun文件夹,fun文件夹下面有fun_file.txt
6、适用场景
1)你想表示对象的部分-整体层次结构,当有部分与整体的明确关系,应该使用组合模式。
2)你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。