-
Notifications
You must be signed in to change notification settings - Fork 0
组合模式
ZHI-XINHUA edited this page Jan 11, 2019
·
1 revision
组合模式将对象组织到树结构中,可以用来描述整体与部分的关系。
忽略各个角色的细节,下图的角色结构如下:
-
抽象构件(Component)角色:给参加组合的对象规定一个接口,规范共有的接口及默认行为。这个接口可以用来管理所以的子对象,要提供一个接口 以规范取得和管理下层组件的接口,包括add()、remove()已经getChild()之类的方法
-
树叶构件(Leaf)角色:代办参加组合的树叶对象。一个树叶没有下级的子对象。定义出参加组合的原始对象行为。
-
树枝构件(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象的行为
在Component里面声明所有用来管理子类对象的方法,包括add()、remove()和getChild()方法。这样做的好处是所有的构建类都有相同的接口。在客户端看来,树叶类对象与组合类对象的区别在接口层次上消失了,客户端可以同等对待所有对象,这就是透明形式的组合模式。
缺点是不够安全,树叶类对象与组合类对象本质上是有区别的,因此add()、remove()和getChild()方法对于树叶字节是没有意义的。虽然编译时期不会出错,但是在运行时期会出错。
uml 结构图如下
**(1)抽象文件 IFile **
/**
* 透明模式
* 文件接口
* 抽象构件角色:给参加组合的对象规定一个接口,规范共有的接口及默认行为。这个接口可以用来管理所以的子对象,要提供一个接口
* 以规范取得和管理下层组件的接口,包括add()、remove()已经getChild()之类的方法
*/
public interface IFile {
/********1、有的接口及默认行为:公共行为,只是简单列出几个方法**********/
//获取文件名称
String getFileName();
//删除文件
void delete();
/********2、管理下层组件:文件夹才有的行为,只是简单列出几个方法****************/
//创建文件
void createFile(IFile iFile);
//创建文件夹
void createFolder(IFile iFile);
//删除文件
void deleteFile(IFile iFile);
//获取文件夹下所有文件
List<IFile> getFiles();
}
(2)文件类 File
/**
* 透明模式
* 文件
* 树叶构件(Leaf)角色:代办参加组合的树叶对象。一个树叶没有下级的子对象。定义出参加组合的原始对象行为。
*/
public class File implements IFile{
private String fileName;
public File(String fileName){
this.fileName = fileName;
}
@Override
public String getFileName() {
return fileName;
}
@Override
public void delete() {
//假装删除
fileName ="";
}
/**
* 文件夹特有方法,File不支持的方法
*/
@Override
public void createFile(IFile iFile) {
throw new UnsupportedOperationException();
}
/**
* 文件夹特有方法,File不支持的方法
*/
@Override
public void createFolder(IFile iFile) {
throw new UnsupportedOperationException();
}
/**
* 文件夹特有方法,File不支持的方法
*/
@Override
public void deleteFile(IFile iFile) {
throw new UnsupportedOperationException();
}
/**
* 文件夹特有方法,File不支持的方法
*/
@Override
public List<IFile> getFiles() {
throw new UnsupportedOperationException();
}
}
(3)文件夹类 Folder
/**
* 文件夹
* 树枝构件(Composite)角色:代表参加组合的有子对象的对象,并给出树枝构件对象的行为
*/
public class Folder implements IFile{
private String folderName;
private List<IFile> files;
public Folder(String folderName,List<IFile> files){
this.folderName = folderName;
this.files = files;
}
@Override
public String getFileName() {
return folderName;
}
@Override
public void delete() {
files = null;
}
@Override
public void createFile(IFile iFile) {
files.add(iFile);
}
@Override
public void createFolder(IFile iFile) {
files.add(iFile);
}
@Override
public void deleteFile(IFile iFile) {
files.remove(iFile);
}
@Override
public List<IFile> getFiles() {
return files;
}
}
代码可看出,文件类File 存在 文件夹的特有方法,这是没必要而且调用时候会抛出异常。所以,以下安全式解决了这问题。
Component里面声明公共方法,这样的做法安全。编译时期不会出错,运行时期也不会出错。但是不够透明度。
uml结构图如下
(1)抽象文件 IFile
去掉文件夹特有的方法,保留公共方法
/**
* Created by xh.zhi on 2018-9-13.
* 安全模式
* 文件接口
* 抽象构件角色:给参加组合的对象规定一个接口,规范共有的接口及默认行为。这个接口可以用来管理所以的子对象,要提供一个接口
* 以规范取得和管理下层组件的接口,包括add()、remove()已经getChild()之类的方法
*/
public interface IFile {
/********有的接口及默认行为:公共行为,只是简单列出几个方法**********/
//获取文件名称
String getFileName();
//删除文件
void delete();
}
(2)文件 File
/**
* 安全模式
* 文件
* 树叶构件(Leaf)角色:代办参加组合的树叶对象。一个树叶没有下级的子对象。定义出参加组合的原始对象行为。
*/
public class File implements IFile {
private String fileName;
public File(String fileName){
this.fileName = fileName;
}
@Override
public String getFileName() {
return fileName;
}
@Override
public void delete() {
//假装删除
fileName ="";
}
}
测试类
public class MainTest {
public static void main(String[] args) {
List<IFile> files1 = new ArrayList<IFile>();
List<IFile> files2 = new ArrayList<IFile>();
//模拟文件夹下面的文件
for(int i=1;i<=5;i++){
files1.add(new File("test"+i+".java"));
files2.add(new File("速度与激情"+i+".avi"));
}
Folder movie = new Folder("我的电影",files2);
//创建root
Folder c = new Folder("C盘",files1);
//创建文件
c.createFile(new File("需求文档.doc"));
//创建子文件夹
c.createFolder(movie);
List<IFile> list = c.getFiles();
for (IFile node:list) {
//子文件夹
if(node instanceof Folder){
System.out.println("======"+node.getFileName()+"========");
Folder folder = (Folder) node;
List<IFile> cnodes = folder.getFiles();
for (IFile cnode:cnodes) {
System.out.println(cnode.getFileName());
}
System.out.println("======"+node.getFileName()+"========");
}else{
System.out.println(node.getFileName());
}
}
}
}
运行结果:
test1.java
test2.java
test3.java
test4.java
test5.java
需求文档.doc
======我的电影========
速度与激情1.avi
速度与激情2.avi
速度与激情3.avi
速度与激情4.avi
速度与激情5.avi
======我的电影========
设计模式