任务描述
使用组合模式设计一个杀毒软件(AntiVirus)的框架,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒,文件种类包括文本文件 TextFile,图片文件 ImageFile、视频文件 VideoFile。
本关任务:根据 UML 类图编程模拟实现。
实现方式
确保应用的核心模型能够以树状结构表示。 尝试将其分解为简单元素和容器。 记住, 容器必须能够同时包含简单元素和其他容器。
声明组件接口及其一系列方法, 这些方法对简单和复杂元素都有意义。
创建一个叶节点类表示简单元素。 程序中可以有多个不同的叶节点类。
创建一个容器类表示复杂元素。 在该类中, 创建一个数组成员变量来存储对于其子元素的引用。 该数组必须能够同时保存叶节点和容器, 因此请确保将其声明为组合接口类型。实现组件接口方法时, 记住容器应该将大部分工作交给其子元素来完成。
最后, 在容器中定义添加和删除子元素的方法。
记住,这些操作可在组件接口中声明。 这将会违反接口隔离原则,因为叶节点类中的这些方法为空。 但是,这可以让客户端无差别地访问所有元素, 即使是组成树状结构的元素。
编程要求
根据提示,在右侧编辑器 Begin-End 内补充 "AbstractFile.java" 和 "Folder.java" 文件代码,其它文件不需要修改。
Reference Answer (1)
package step1;
//抽象文件类:抽象构件
/********** Begin *********/
public abstract class AbstractFile {
public abstract void add(AbstractFile element);
public abstract void remove(AbstractFile element);
public abstract void scan();
}
/********** End *********/
package step1;
//文件夹类:容器构件
import java.util.ArrayList;
class Folder extends AbstractFile {
private ArrayList<AbstractFile> fileList = new ArrayList<>();
private String fileName;
public Folder(String fileName) {
this.fileName = fileName;
}
@Override
public void add(AbstractFile element) {
fileList.add(element);
}
@Override
public void remove(AbstractFile element) {
fileList.remove(element);
}
@Override
public void scan() {
for (AbstractFile file : fileList) {
file.scan();
}
}
}
Reference Answer (2)
AbstractFile.java
package step1;
//抽象文件类:抽象构件
/********** Begin *********/
public abstract class AbstractFile {
public String fileName;
public AbstractFile(String fileName) {
this.fileName = fileName;
}
public abstract void add(AbstractFile element);
public abstract void remove(AbstractFile element);
public abstract void scan();
}
/********** End *********/
Folder.java
package step1;
//文件夹类:容器构件
import java.util.ArrayList;
class Folder extends AbstractFile {
private ArrayList<AbstractFile> fileList = new ArrayList<>();
public Folder(String fileName) {
super(fileName);
}
@Override
public void add(AbstractFile element) {
fileList.add(element);
}
@Override
public void remove(AbstractFile element) {
fileList.remove(element);
}
@Override
public void scan() {
for (AbstractFile file : fileList) {
file.scan();
}
}
}
第三步的第一种处理方法:删除ImageFile
, TextFile
, 和 VideoFile
类的“private String fileName;”,并将各自构造函数中的“this.fileName = fileName;”替换为“super(fileName)”。
注:
变量隐藏(Shadowing):在 VideoFile
等类中重新声明了 private String fileName;
,这实际上隐藏了父类 AbstractFile
中的 fileName
成员变量。因此,当在 VideoFile
等类的构造函数中设置 this.fileName = fileName;
时,实际上是在设置子类中的 fileName
而不是父类中 fileName
的。未调用父类构造函数:应该在 VideoFile
的构造函数中显式调用父类的构造函数来初始化父类中的 fileName
。
第三步的第二种处理方法:
保留ImageFile
, TextFile
, 和 VideoFile
类的“private String fileName;”,并在“this.fileName = fileName;”之前添加“super(fileName)”。