组合模式浅析

2020-06-28 15:57:41 浏览数 (1)

组合模式是指将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。

在平时,我们在应用中碰到的文件系统(文件是叶子节点,文件目录是树枝节点,可以包含文件或文件目录);企业结构(企业有很多部门,部分有些是没有下属部门,有些是有的);另外,还有向分类层级关系等,这些都可以看做是组合模式的典型应用。

一. 组合模式的基本介绍

意图

将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。

结构

组合模式的基本结构如下:

这里涉及到的参与者有如下几种:

  • Component角色
    • 这是一抽象角色,它给参加组合的对象规定一个接口,规范共有的接口及默认行为。
  • Leaf角色
    • 在组合中表示叶节点对象,叶子节点没有子节点。
  • Composite角色
    • 代表参加组合的有子对象的对象,定义出这样的对象的行为。
  • Client角色
    • 通过Component接口操纵组件的对象

参与者如何协作?

用户使用Component类接口与组合结构中的对象进行交互。如果接收者是一个叶子节点,则直接处理请求。如果接收者是Composite,它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。

二. 组合模式的示例

接下来以一个文件、目录的示例来说明一下组合模式。其中File是叶子节点,Directory是Composite构件。

  • Entry(Component角色)

代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.composite;

public abstract class Entry {

   abstract void add(Entry e);

   abstract void list();

}
  • File(Leaf角色)
代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.composite;

public class File extends  Entry {

  private String name;

  public File(String name) {
    this.name = name;
  }

  @Override
  public void list() {
    System.out.println(name);

  }

  /**
   * @return the name
   */
  public String getName() {
    return name;
  }

  @Override
  void add(Entry e) {
    //叶子节点不能添加子节点,dothing 
  }
  

}
  • Directory(树枝角色)
代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.composite;

import java.util.ArrayList;
import java.util.List;

public class Directory extends Entry {

 private String name;
 private List<Entry> childEntryList = new ArrayList<>();
  
  public Directory(String name) {
    this.name = name;
  }

  

  @Override
  void add(Entry e) {
    childEntryList.add(e);

  }

  @Override
  public void list() {
    String currDir = this.getName()   "/";
    System.out.println(currDir);
    for(Entry entry : childEntryList) {
      System.out.print(currDir);
      entry.list();

    }

  }

  /**
   * @return the name
   */
  public String getName() {
    return name;
  }
}
  • Client(Client角色)
代码语言:javascript复制
package com.wangmengjun.tutorial.designpattern.composite;

public class Client {
  public static void main(String[] args) {
        Entry music = new Directory("音乐");

          Entry music1 = new File("冰雨.mp3");
          Entry music2 = new File("吻别.mp3");
          Entry music3 = new File("等一分钟.mp3");
          Entry music4 = new File("小镇姑娘.mp3");
          Entry music5 = new File("一千个伤心的理由.mp3");
          music.add(music1);
          music.add(music2);
          music.add(music3);
          music.add(music4);
          music.add(music5);

          Entry enpty = new Directory("空目录");
          music.add(enpty);

          music.list(); 
  }
} 

运行一下:

代码语言:javascript复制
音乐/
音乐/冰雨.mp3
音乐/吻别.mp3
音乐/等一分钟.mp3
音乐/小镇姑娘.mp3
音乐/一千个伤心的理由.mp3
音乐/空目录/

三. 小结

优缺点

优点:

(1):组合模式可以很容易地增加新种类的构件

(2):使用组合模式可以使客户端变得容易设计,因为客户端不需要知道构件是树叶构件还是树枝构件。

缺点:

(1):使用组合模式后,控制树枝构件的类型就不太容易

(2):用继承的方法来增加新的行为会变得困难。

参考

[1]. 阎宏. Java与模式.电子工业出版社

[2]. Erich Gamma. 设计模式-可复用面向对象软件的基础. 机械工业出版社.

0 人点赞