组合模式-Composite(Java实现)

匿名 (未验证) 提交于 2019-12-02 21:53:52

组合模式-Composite

Composite模式使得用户对单个对象和组合对象的使用具有一致性.

以<<图解设计模式>>的文件例子来说: 文件夹是文件的组合, 文件是单个对象, 文件夹是多个文件的组合. 不过对用户来说, 无论是文件还是文件夹, 他希望使用一个统一的方法来管理他们.这就需要将他们再次抽象出来.

解读一下这个类图就明白了:

1. 文件是一个组件

2. 文件夹也是一个组件

3. 文件夹里有很多组件:

Component抽象类

这是文件 文件夹的抽象定义类--组件类

/**  * 这里是文件/文件夹 的统一抽象类 "组件类"  */ public abstract class Component {     /**      * parent是父组件的指针, 也就是本例子中的"父级目录"      */     protected Component parent;      /**      * 获取组件名字      */     public abstract String getName();      /**      * 获取组件的大小      */     public abstract int getSize();      /**      * @implNote 向一个组件中添加一个组件.      * @implSpec 组合模式中的叶子(Leaf)节点不可以使用这个方法, 用例子说明的话:      * 一个文件不可以添加一个文件或文件夹, 只能是文件夹来添加文件或文件夹      */     public Component add(Component entry) {         throw new RuntimeException("不支持此类操作...");     }      public void printList() {         printList("");     }      protected abstract void printList(String prefix);      /**      * 获取绝对路径      */     public String getFullName() {         StringBuilder fullName = new StringBuilder();         Component entry = this;         do {             fullName.insert(0, "/" + entry.getName());             entry = entry.parent;         } while (entry != null);         return fullName.toString();     }      /**      * 其中的getSize() 会被子类重写, 因为文件大小可以很容易知道, 但是文件夹大小需要递归计算      */     @Override     public String toString() {         return getName() + " (" + getSize() + ")";     } }

MyFile类

MyFile类在组合模式中是Leaf(叶子)节点, 因为他不会包含其他组件.

我们可以把组件模式想象成一颗树(绿色表示文件夹, 橙色表示文件):

组合模式的叶子节点指的是文件节点, 因为文件永远也不会有子节点.

而绿的c1节点虽然现在是叶子节点, 但是如果给c1文件夹添加了一个文件的话, 他就不再是叶子节点了.

组合模式里无法继续添加子节点的就被称作Leaf(叶子)

上面那个树, 等价于下图:

public class MyFile extends Component {     private String name;     private int size;      public MyFile(String name, int size) {         this.name = name;         this.size = size;     }      @Override     public String getName() {         return this.name;     }      @Override     public int getSize() {         return this.size;     }      @Override     protected void printList(String prefix) {         System.out.println(prefix + "/" + this.toString());     } }

MyDirectory类

MyDirectory类作为一个文件夹, 可以包含其他组件(文件/文件夹)

public class MyDirectory extends Component {      private String name;     private ArrayList<Component> substance = new ArrayList<>();      public MyDirectory(String name) {         this.name = name;     }      @Override     public String getName() {         return this.name;     }      /**      * 获取文件夹的大小:      * 1. size一开始是0      * 2. 如果是文件, 那么直接把文件的大小加到size上      * 3. 如果是文件夹, 那么就递归地查出该文件夹的大小, 然后加到size上.      */     @Override     public int getSize() {         int size = 0;         for (Component entry : substance) {             size += entry.getSize();         }         return size;     }      /**      * 像一个文件夹中添加一个文件或文件夹      */     @Override     public Component add(Component entry) {         substance.add(entry);         entry.parent = this;         return this;     }      /**      * 1. 打印当前目录的路径      * 2. 然后打印出子目录, 子文件的路径      * 3. 子目录再打印子子目录/子子文件的路径...如此递归      */     @Override     protected void printList(String prefix) {         System.out.println(prefix + "/" + this.toString());         for (Component entry : substance) {             entry.printList(prefix + "/" + name);         }     } } 

  

Main

用于测试运行

public class Main {     public static void main(String[] args) {          /* 本例子目录结构如下:           一级目录   二级目录   三级目录             a1             |-------b1             |-------b2             |             a2             |-------c1                     |-------Composite.java                     |-------king.python              |-------c2          */          MyDirectory a1 = new MyDirectory("a1");         MyDirectory a2 = new MyDirectory("a2");          MyDirectory b1 = new MyDirectory("b1");         MyDirectory b2 = new MyDirectory("b2");         a1.add(b1).add(b2);          MyDirectory c1 = new MyDirectory("c1");         MyDirectory c2 = new MyDirectory("c2");         a2.add(c1).add(c2);          MyFile java = new MyFile("Composite.java", 100);         MyFile python = new MyFile("king.python", 214);         c1.add(java).add(python);          /*-****** getFullName() ************-*/         System.out.println(java.getFullName());         System.out.println(python.getFullName());         System.out.println("");         /*-****** getFullName() ************-*/         a1.printList();         System.out.println("-----");         a2.printList();     } } 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!