前言
最近由windows转到了Linux,但是似乎对Linux一无所知,只知道是装逼神器。但是慢慢滴,Linux的文件系统假装让我产生了兴趣(实际上是巧遇)。下面让我们来看看Linux文件系统的一段介绍。
Linux 系统中的一切都是存放在唯一的 虚拟文件系统中的,这个 虚拟文件系统是树状的结构以一个根目录开始。启动系统后,先有这个 虚拟文件系统,再识别出各个硬盘, 再把某个硬盘的某个分区挂载到这个 虚拟文件系统的某个子树上(即分区用某个子目录来表示),再确定分区对应的子目录文件系统,最后的文件就存放在这个特定的文件系统中。 也就是说, Linux 系统是通过 “虚拟文件系统-硬盘-硬盘上的分区-分区上的特定文件系统-特定文件系统中的文件” 这样的顺序来访问一个文件的。
回到本文的主题。树形结构在软件中随处可见,例如操作系统中的目录结构、应用软件中的菜单、办公系统中的公司组织结构等等,如何运用面向对象的方式来处理这种树形结构就是组合模式需要解决的问题。
概述
组合模式(Composite Pattern)允许你将对象促合成树形结构来表现“整体/部分”层次结构。组合能让客户以一直的方式处理个别对象以及对象组合。
换句话说,使用组合结构,我们能把相同的操作应用在组合和个别对象上,即,大多数情况下,我们可以忽略对象组合和个别对象之间的差别。好比,在数据结构中,对树节点的操作,不分根节点还是叶子节点。也就是一致性地处理树形结构中的叶子节点(不包含子节点的节点)和容器节点(包含子节点的节点)。
类图
- Component: 组合中的对象声明接口,在适当的情况下,实现所有类共有的默认行为。
- Leaf:叶子对象。
- Composite: 容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作。
设计模式的实现
使用场景
在文件系统中,可能存在很多种格式的文件,如图片,文本文件、视频文件等等,这些不同的格式文件的浏览方式都不同,同时对文件夹的浏览就是对文件夹中文件的浏览,但是对于客户而言都是浏览文件,两者之间不存在什么差别,现在只用组合模式来模拟浏览文件。
代码实现
package Component;
/**
* <p>ClassName File
* <p>Description 文件夹类
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:08
*/
public abstract class File {
String name;
public File(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public abstract void display();
}
package Component;
import java.util.ArrayList;
import java.util.List;
/**
* <p>ClassName Folder
* <p>Description 文件夹类
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:19
*/
public class Folder extends File{
private List<File> files;
public Folder(String name){
super(name);
files = new ArrayList<File>();
}
/**
* 浏览文件夹中的文件
*/
public void display() {
for(File file : files){
file.display();
}
}
/**
* @desc 向文件夹中添加文件
* @param file
* @return void
*/
public void add(File file){
files.add(file);
}
/**
* @desc 从文件夹中删除文件
* @param file
* @return void
*/
public void remove(File file){
files.remove(file);
}
}
package Component;
/**
* <p>ClassName ImageFile
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:20
*/
public class ImageFile extends File{
public ImageFile(String name) {
super(name);
}
public void display() {
System.out.println("这是图像文件,文件名:" + super.getName());
}
}
package Component;
/**
* <p>ClassName TextFile
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:20
*/
public class TextFile extends File {
public TextFile(String name) {
super( name );
}
public void display() {
System.out.println( "这是文本文件,文件名:" + super.getName() );
}
}
package Component;
/**
* <p>ClassName VideoFile
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:21
*/
public class VideoFile extends File {
public VideoFile(String name) {
super(name);
}
public void display() {
System.out.println("这是影像文件,文件名:" + super.getName());
}
}
package Component;
/**
* <p>ClassName Client
* <p>Description
* <p>Author ChongLou
* <p>Version
* <p>Date 2017/10/22 17:22
*/
public class Client {
public static void main(String[] args) {
/**
* 我们先建立一个这样的文件系统
* DesktopFolder
*
* a.txt b.jpg cFolder
* c_1.text c_1.rmvb c_1.jpg
*
*/
//总文件夹---DesktopFolder
Folder zwjj = new Folder( "DesktopFolder" );
//向总文件夹中放入三个文件:1.txt、2.jpg、1文件夹
TextFile aText = new TextFile( "a.txt" );
ImageFile bImager = new ImageFile( "b.jpg" );
Folder cFolder = new Folder( "cFolder" );
zwjj.add( aText );
zwjj.add( bImager );
zwjj.add( cFolder );
//向C文件夹中添加文件:c_1.txt、c_1.rmvb、c_1.jpg
TextFile cText = new TextFile( "c_1.txt" );
ImageFile cImage = new ImageFile( "c_1.jpg" );
VideoFile cVideo = new VideoFile( "c_1.rmvb" );
cFolder.add( cText );
cFolder.add( cImage );
cFolder.add( cVideo );
//遍历C文件夹
cFolder.display();
//将c_1.txt删除
cFolder.remove( cText );
System.out.println( "-----------------------" );
cFolder.display();
}
}
运行结果
总结
- 组合模式提供一个结构,可同时包容个别对象和组合对象;
- 组合模式允许客户对个别对象以及组合对象一视同仁;
- 组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
- 在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。