博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式(十一)Composite模式
阅读量:5115 次
发布时间:2019-06-13

本文共 5449 字,大约阅读时间需要 18 分钟。

  Composite模式模式能够使容器与内容具有一致性,创造出递归结构。有时,与将文件夹和文件都作为目录条目看待一样,将容器和内容作为同一种东西看待,可以帮助我们方便地处理问题。在容器中既可以放入内容,也可以放入小容器,然后在那个小容器中,又可以放入更小的容器。这样,就形成了容器结构、递归结构。

  示例程序类图如上图。

1 package bigjunoba.bjtu.composite; 2  3 public abstract class Entry { 4     public abstract String getName();                               // 获取名字 5     public abstract int getSize();                                  // 获取大小 6     public Entry add(Entry entry) throws FileTreatmentException {   // 加入目录条目 7         throw new FileTreatmentException(); 8     } 9     public void printList() {                                       // 为一览加上前缀并显示目录条目一览10         printList("");11     }12     protected abstract void printList(String prefix);               // 为一览加上前缀13     public String toString() {                                      // 显示代表类的文字14         return getName() + " (" + getSize() + ")";15     }16 }

  Entry类是一个表示目录条目的抽象类。为了能将文件夹Directory和文件File统一起来,所以设计了Entry类。其中printList方法有两种形式,称为重载。其中带参数的printList方法可见性是protected,即只能被Entry类的子类调用。

1 package bigjunoba.bjtu.composite; 2  3 public class File extends Entry { 4     private String name; 5     private int size; 6     public File(String name, int size) { 7         this.name = name; 8         this.size = size; 9     }10     public String getName() {11         return name;12     }13     public int getSize() {14         return size;15     }16     protected void printList(String prefix) {17         System.out.println(prefix + "/" + this);18     }19 }

  File类是表示文件的类,调用构造函数,就会根据传入的文件名和文件大小生成文件实例。其中的this表示父类中的toString方法。

1 package bigjunoba.bjtu.composite; 2  3 import java.util.Iterator; 4 import java.util.ArrayList; 5  6 public class Directory extends Entry { 7     private String name;                    // 文件夹的名字 8     private ArrayList
directory = new ArrayList
(); // 文件夹中目录条目的集合 9 public Directory(String name) { // 构造函数10 this.name = name;11 }12 public String getName() { // 获取名字13 return name;14 }15 16 public int getSize() { // 获取大小17 int size = 0;18 Iterator
it = directory.iterator();19 while (it.hasNext()) {20 Entry entry = (Entry)it.next();21 size += entry.getSize();22 }23 return size;24 }25 26 public Entry add(Entry entry) { // 增加目录条目27 directory.add(entry);28 return this;29 }30 31 protected void printList(String prefix) { // 显示目录条目一览32 System.out.println(prefix + "/" + this);33 Iterator
it = directory.iterator();34 while (it.hasNext()) {35 Entry entry = (Entry)it.next();36 entry.printList(prefix + "/" + name);37 }38 }39 }

  Directory类是表示文件夹的类。这里用泛型集合来保存文件夹中的目录条目。getSize方法返回集合中所有元素的大小的总和。

  这里注意size += entry.getSize();不管entry是哪个类的实例,都可以通过getSize方法得到它的大小。这就是该模式的特征--容器与内容一致性-的表现。

  注意这里使用了递归,如果entry是Directory类的实例,调用 entry.getSize()时会将该文件夹下的所有目录条目的大小加起来,如果还有子文件夹,又会调用子文件夹的getSize方法。即getSize方法的递归调用与Composite模式的结构是相对应的。

  add方法不会判断接收到的是文件夹还是文件,而是通过委托给ArrayList类来实现。printList方法也会递归调用,不多解释了。

 

1 package bigjunoba.bjtu.composite;2 3 public class FileTreatmentException extends RuntimeException {4     public FileTreatmentException() {5     }6     public FileTreatmentException(String msg) {7         super(msg);8     }9 }

 

  由于调用add方法抛出的异常类并非Java类库的自带异常类,所以要编写自己的异常类。

1 package bigjunoba.bjtu.composite; 2  3 public class Main { 4     public static void main(String[] args) { 5         try { 6             System.out.println("Making root entries..."); 7             Directory rootdir = new Directory("root"); 8             Directory bindir = new Directory("bin"); 9             Directory tmpdir = new Directory("tmp");10             Directory usrdir = new Directory("usr");11             rootdir.add(bindir);12             rootdir.add(tmpdir);13             rootdir.add(usrdir);14             bindir.add(new File("vi", 10000));15             bindir.add(new File("latex", 20000));16             rootdir.printList();17 18             System.out.println("");19             System.out.println("Making user entries...");20             Directory yuki = new Directory("yuki");21             Directory hanako = new Directory("hanako");22             Directory tomura = new Directory("tomura");23             usrdir.add(yuki);24             usrdir.add(hanako);25             usrdir.add(tomura);26             yuki.add(new File("diary.html", 100));27             yuki.add(new File("Composite.java", 200));28             hanako.add(new File("memo.tex", 300));29             tomura.add(new File("game.doc", 400));30             tomura.add(new File("junk.mail", 500));31             rootdir.printList();32         } catch (FileTreatmentException e) {33             e.printStackTrace();34         }35     }36 }

  Main类作为测试类,也不做过多解释。

Making root entries.../root (30000)/root/bin (30000)/root/bin/vi (10000)/root/bin/latex (20000)/root/tmp (0)/root/usr (0)Making user entries.../root (31500)/root/bin (30000)/root/bin/vi (10000)/root/bin/latex (20000)/root/tmp (0)/root/usr (1500)/root/usr/yuki (300)/root/usr/yuki/diary.html (100)/root/usr/yuki/Composite.java (200)/root/usr/hanako (300)/root/usr/hanako/memo.tex (300)/root/usr/tomura (900)/root/usr/tomura/game.doc (400)/root/usr/tomura/junk.mail (500)

   测试结果如上图,一目了然。

 

 

转载于:https://www.cnblogs.com/BigJunOba/p/8708329.html

你可能感兴趣的文章
django迁移数据库错误
查看>>
yii 跳转页面
查看>>
洛谷 1449——后缀表达式(线性数据结构)
查看>>
Data truncation: Out of range value for column 'Quality' at row 1
查看>>
Dirichlet分布深入理解
查看>>
(转)Android之发送短信的两种方式
查看>>
字符串处理
查看>>
HtmlUnitDriver 网页内容动态抓取
查看>>
ad logon hour
查看>>
获得进程可执行文件的路径: GetModuleFileNameEx, GetProcessImageFileName, QueryFullProcessImageName...
查看>>
证件照(1寸2寸)拍摄处理知识汇总
查看>>
罗马数字与阿拉伯数字转换
查看>>
Eclipse 反编译之 JadClipse
查看>>
Python入门-函数
查看>>
[HDU5727]Necklace(二分图最大匹配,枚举)
查看>>
距离公式汇总以及Python实现
查看>>
设计模式之装饰者模式
查看>>
一道不知道哪里来的容斥题
查看>>
Blender Python UV 学习
查看>>
window添加右键菜单
查看>>