组合模式通过子类聚合父类,从而解决树形结构的整体-部分问题。典型的例子有公司架构体系,文件系统等。
组合模式有两种类型:安全模式和透明模式。
安全模式:Component中只保留最基础的功能,差异性功能都留到子类去实现。
透明模式:Component中定义全部功能,叶子节点会冗余多余功能。
安全模式:
package composite.safeComposite;
public abstract class FileComponent {
String name;
public FileComponent(String name) {
super();
this.name = name;
}
public abstract void listFiles();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package composite.safeComposite;
public class FileLeaf extends FileComponent{
public FileLeaf(String name) {
super(name);
}
@Override
public void listFiles() {
System.out.println(getName());
}
}
package composite.safeComposite;
import java.util.ArrayList;
import java.util.List;
public class FolderComposite extends FileComponent{
List<FileComponent> files=new ArrayList<>();
public FolderComposite(String name) {
super(name);
}
@Override
public void listFiles() {
files.stream().forEach(FileComponent::listFiles);
}
public void addFile(FileComponent myFile) {
files.add(myFile);
}
public void removeFile(FileComponent myFile) {
files.remove(myFile);
}
}
package composite.safeComposite;
public class Client {
public static void main(String[] args) {
FolderComposite root=new FolderComposite("总文件夹");
FileLeaf firstGradeFileA=new FileLeaf("一级文件-a.txt");
FileLeaf firstGradeFileB=new FileLeaf("一级文件-b.txt");
FolderComposite firstGradeFolder=new FolderComposite("一级文件夹");
root.addFile(firstGradeFileA);
root.addFile(firstGradeFileB);
root.addFile(firstGradeFolder);
FileLeaf secondGradeFileA=new FileLeaf("二级文件-a.txt");
FileLeaf secondGradeFileB=new FileLeaf("二级文件-b.txt");
firstGradeFolder.addFile(secondGradeFileA);
firstGradeFolder.addFile(secondGradeFileB);
root.listFiles();
System.out.println("##################");
root.removeFile(firstGradeFileA);
root.listFiles();
}
}
透明模式:
package composite.transparentComposite;
public abstract class FileComponent {
String name;
public FileComponent(String name) {
super();
this.name = name;
}
public abstract void listFiles();
public abstract void addFile(FileComponent FileComponent);
public abstract void removeFile(FileComponent FileComponent);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package composite.transparentComposite;
public class FileLeaf extends FileComponent{
public FileLeaf(String name) {
super(name);
}
@Override
public void listFiles() {
System.out.println(getName());
}
@Override
public void addFile(FileComponent FileComponent) {
throw new RuntimeException("不支持的操作!");
}
@Override
public void removeFile(FileComponent FileComponent) {
throw new RuntimeException("不支持的操作!");
}
}
package composite.transparentComposite;
import java.util.ArrayList;
import java.util.List;
public class FolderComposite extends FileComponent{
List<FileComponent> files=new ArrayList<>();
public FolderComposite(String name) {
super(name);
}
@Override
public void listFiles() {
files.stream().forEach(FileComponent::listFiles);
}
@Override
public void addFile(FileComponent myFile) {
files.add(myFile);
}
@Override
public void removeFile(FileComponent myFile) {
files.remove(myFile);
}
}
package composite.transparentComposite;
public class Client {
public static void main(String[] args) {
FileComponent root=new FolderComposite("总文件夹");
FileComponent firstGradeFileA=new FileLeaf("一级文件-a.txt");
FileComponent firstGradeFileB=new FileLeaf("一级文件-b.txt");
FileComponent firstGradeFolder=new FolderComposite("一级文件夹");
root.addFile(firstGradeFileA);
root.addFile(firstGradeFileB);
root.addFile(firstGradeFolder);
FileComponent secondGradeFileA=new FileLeaf("二级文件-a.txt");
FileComponent secondGradeFileB=new FileLeaf("二级文件-b.txt");
firstGradeFolder.addFile(secondGradeFileA);
firstGradeFolder.addFile(secondGradeFileB);
root.listFiles();
System.out.println("##################");
root.removeFile(firstGradeFileA);
root.listFiles();
}
}
打印结果:
二级文件-a.txt
二级文件-b.txt
##################
一级文件-b.txt
二级文件-a.txt
二级文件-b.txt
小结:
1.注意比较两种模式Leaf中方法以及Client的调用方式。
2.使用安全模式或使用透明模式应该酌情考虑。
使用安全模式,Leaf不会存在冗余方法,但是Client需要自行区分Leaf和Composite。一般Leaf和Composite差异性行为较多时,应该使用安全模式。
使用透明模式,Leaf会存在冗余方法,但是Client对Component的使用是透明的,不需要再去区分Leaf和Composite的类型。一般需要Client对Component透明时,需要是透明模式。