持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第33天,点击查看活动详情
10 组合模式
-
可以统一单个对象和组合对象的处理逻辑。
-
实现:设计一个类来表示文件系统中的目录,能方便地实现下面这些功能
- 动态地添加、删除某个目录下的子目录或文件;
- 统计指定目录下的文件个数;
- 统计指定目录下的文件总大小。
public abstract class FileSystemNode {
protected String path;
public FileSystemNode(String path) {
this.path = path;
}
public abstract int countNumOfFiles();
public abstract long countSizeOfFiles();
public String getPath() {
return path;
}
}
public class File extends FileSystemNode {
public File(String path) {
super(path);
}
@Override
public int countNumOfFiles() {
return 1;
}
@Override
public long countSizeOfFiles() {
java.io.File file = new java.io.File(path);
if (!file.exists()) return 0;
return file.length();
}
}
public class Directory extends FileSystemNode {
private List<FileSystemNode> subNodes = new ArrayList<>();
public Directory(String path) {
super(path);
}
@Override
public int countNumOfFiles() {
int numOfFiles = 0;
for (FileSystemNode fileOrDir : subNodes) {
numOfFiles += fileOrDir.countNumOfFiles();
}
return numOfFiles;
}
@Override
public long countSizeOfFiles() {
long sizeofFiles = 0;
for (FileSystemNode fileOrDir : subNodes) {
sizeofFiles += fileOrDir.countSizeOfFiles();
}
return sizeofFiles;
}
public void addSubNode(FileSystemNode fileOrDir) {
subNodes.add(fileOrDir);
}
public void removeSubNode(FileSystemNode fileOrDir) {
int size = subNodes.size();
int i = 0;
for (; i < size; ++i) {
if (subNodes.get(i).getPath().equalsIgnoreCase(fileOrDir.getPath())) {
break;
}
}
if (i < size) {
subNodes.remove(i);
}
}
}
文件和目录类都设计好了,继而使用它们来表示一个文件系统中的目录树结构。具体的代码示例如下所示:
public class Demo {
public static void main(String[] args) {
/**
* /
* /wz/
* /wz/a.txt
* /wz/b.txt
* /wz/movies/
* /wz/movies/c.avi
* /xzg/
* /xzg/docs/
* /xzg/docs/d.txt
*/
Directory fileSystemTree = new Directory("/");
Directory node_wz = new Directory("/wz/");
Directory node_xzg = new Directory("/xzg/");
fileSystemTree.addSubNode(node_wz);
fileSystemTree.addSubNode(node_xzg);
File node_wz_a = new File("/wz/a.txt");
File node_wz_b = new File("/wz/b.txt");
Directory node_wz_movies = new Directory("/wz/movies/");
node_wz.addSubNode(node_wz_a);
node_wz.addSubNode(node_wz_b);
node_wz.addSubNode(node_wz_movies);
File node_wz_movies_c = new File("/wz/movies/c.avi");
node_wz_movies.addSubNode(node_wz_movies_c);
Directory node_xzg_docs = new Directory("/xzg/docs/");
node_xzg.addSubNode(node_xzg_docs);
File node_xzg_docs_d = new File("/xzg/docs/d.txt");
node_xzg_docs.addSubNode(node_xzg_docs_d);
System.out.println("/ files num:" + fileSystemTree.countNumOfFiles());
System.out.println("/wz/ files num:" + node_wz.countNumOfFiles());
}
}
- 组合模式,将一组对象组织成树形结构,将单个对象和组合对象都看做树中的节点,以统一处理逻辑,并且它利用树形结构的特点,递归地处理每个子树,依次简化代码实现。使用组合模式的前提在于,业务场景必须能够表示成树形结构。所以,组合模式的应用场景也比较局限,它并不是一种很常用的设计模式。
11 外观模式(门面模式)
- 将多个子系统及其之间的复杂关系和调用流程封装到一个统一的接口或类中以对外提供服务。
- 实现
class Dashboard{ //仪表盘的启动和关闭
public void startup(){
System.out.println("dashboard startup...");
}
public void shutdown(){
System.out.println("dashboard shutdown...");
}
}
class Engine{ //发动机的启动和关闭
public void startup(){
System.out.println("engine startup...");
}
public void shutdown(){
System.out.println("engine shutdown...");
}
}
class SelfCheck{ // 汽车启动后的自检和关闭前的自检
public void startupCheck(){
System.out.println("startup check finished...");
}
public void shutdownCheck(){
System.out.println("shutdown check finished...");
}
}
class Starter{ // 门面类
private Dashboard dashboard;
private Engine engine;
private SelfCheck selfCheck;
public Starter(){
this.dashboard = new Dashboard();
this.engine = new Engine();
this.selfCheck = new SelfCheck();
}
public void startup(){
System.out.println("car startup");
engine.startup();//先调用engine的启动方法 启动引擎
dashboard.startup();// 再调用dashboard的启动方法 启动仪表盘
selfCheck.startupCheck();// 最后调用selfCheck的启动自检方法完成 启动自检
System.out.println("car startup finished");
}
public void shutdown(){
System.out.println("car shutdown");
engine.shutdown();
dashboard.shutdown();
selfCheck.shutdownCheck();
System.out.println("car shutdown finished");
}
}
public class FacadePattern {
public static void main(String[] args) {
Starter starter = new Starter();
starter.startup(); // 调用封装好的方法或接口即可
starter.shutdown();
}
}