前提知识
Linux操作系统中将文件夹当作文件进行处理。
场景引入
假如你现在正在使用一台linux操作系统的计算机。现在你要对你所学的知识进行整理。那么你肯定不会创建很多的文件,因为那样子太乱了。当然你也不会全部创建为文件夹,因为那样你没有办法记录自己的学习笔记。最合理的办法就是在整理的时候既有文件又有文件夹。比如下图:
在这种情况下:我们就把文件和文件夹抽象成一个组件,然后这些组件组合在一起就是组合模式。
观察上面的例子,可以得出:文件夹是包含若干文件的,因此在文件夹类中就有:add()
、remove()
、get()
。这样便于扩展,当然实际情况根据自己需求进行删减。
模式关键
- 底层组件有具体的行为,就像例子中文件是用来写文件的
- 上层文件有一个包含底层文件或上层文件的列表。就像例子中文件夹中可以包含文件夹和文件。
代码实现
interface Component
public interface Component {
// 抽象出来的组件
// 定义抽象组件中有的属性和方法
//为了方便此处就定义一个方法
public void printName();
}
File.class
// 文件类
public class File implements Component{
String name; //属性
public File(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void printName() {
System.out.println("我是文件:"+getName());
}
}
Folder.class
import java.util.ArrayList;
import java.util.List;
// 文件夹类
public class Folder implements Component{
// 一个维持其下层组件列表
private List<Component> list;
String name;
String s; //这个属性不用看,只是为了打印好看,又不想像特别多的方法设置的
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Folder(String name,String s) {
this.s = s; //同样这个属性不用看
this.name = name;
list = new ArrayList<Component>();
}
// 增加下层组件
public void add(Component component){
list.add(component);
}
// 删除下层组件
public void remove(Component component){
list.remove(component);
}
// 获取下层组件
public Component get(int i){
return list.get(i);
}
public void printName() {
System.out.println("我是文件夹:"+getName()+";我有以下文件:");
for(Component component:list){
System.out.print(s);
component.printName();
}
}
}
Test.class
public class Test {
public static void main(String[] args) {
Component studyNote = new Folder("学习笔记"," ");
Component dataProcess = new Folder("数据处理"," ");
Component designPattern = new Folder("设计模式"," ");
Component SVM = new File("支持向量机算法");
Component createType = new Folder("创建型模式"," ");
Component actionType = new Folder("行为型模式"," ");
Component singleton = new File("单例模式");
Component builder = new File("建造者模式");
Component observer = new File("观察者模式");
// 将组件进行组合
((Folder) studyNote).add(dataProcess);
((Folder) studyNote).add(designPattern);
((Folder) dataProcess).add(SVM);
((Folder) designPattern).add(createType);
((Folder) designPattern).add(actionType);
((Folder) createType).add(singleton);
((Folder) createType).add(builder);
((Folder) actionType).add(observer);
//调用方法
studyNote.printName();
}
}
两种方式
安全模式
上面的代码就是安全模式,即上层组件中的方法写在上层组件的类中。具体来说,就是把文件夹中的add()、get()、remove()
等方面放在文件夹类中。这样,当文件从抽象组件Component
类实现的时候,就不用实现这个方法了。
透明模式
将上层组件中的方法也写在抽象组件中。即将文件夹中的
add()、get()、remove()
也写在抽象组件Component
中,这样当文件实现抽象组件时,就要实现这些方法。当然可以使用接口中的默认方法:(与上面不同的代码列在下面)
interface Component
Test.class
模式优点
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
- 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”
模式缺点
-
设计较复杂,客户端需要花更多时间理清类之间的层次关系;
-
不容易限制容器中的构件;
-
不容易用继承的方法来增加构件的新功能;