找回密码
 立即注册
首页 业界区 业界 掌握设计模式--组合模式

掌握设计模式--组合模式

睁扼妤 2025-6-6 14:10:09
组合模式(Composite Pattern)

组合模式(Composite Pattern)是一种结构型设计模式,它用于将对象组织成树形结构,以表示部分-整体的层次结构。通过组合模式,客户端可以统一对待单个对象和组合对象,从而简化了客户端代码的复杂性。
组合模式的核心思想


  • 统一的接口:通过抽象类或接口将单个对象和组合对象统一起来;
  • 递归组合:组合对象中可以包含单个对象或其他组合对象;
  • 透明性:客户端可以一致地调用单个对象和组合对象的方法,而无需区分两者的差异。
组合模式的角色


  • 组件(Component)
    定义单个对象和组合对象的公共接口,例如通用操作(add、remove、getChild等)。
  • 叶子节点(Leaf)
    表示树形结构中的基本单元,不能再包含其他对象。它实现了组件接口,但不支持添加或移除操作。
  • 组合对象(Composite)
    表示树形结构中的复杂单元,可以包含叶子节点或其他组合对象。它实现组件接口,并负责管理其子对象的操作。
示例代码

组合模式解析XML或 HTML 元素结构的代码示例。我们将 XML/HTML 元素看作“部分-整体”结构,其中:

  • 叶子节点(leaf):表示没有子节点的元素(如 <img> 或 )。
  • 组合节点(Composite):表示可以包含其他子元素的元素(如  或 )。
两种节点使用同一种的顶层抽象,属于同一类对象,统称为元素(节点)。
类图

1.png

1. 抽象组件

HTML顶层元素抽象类。你也可以定义一个顶层接口,然后在抽象类中实现基础功能。
  1. public abstract class HTMLElement {
  2.     protected String name;
  3.     public HTMLElement(String name) {
  4.         this.name = name;
  5.     }
  6.     public abstract void render(int level);
  7.     public HTMLElement getChild(int index) {
  8.         throw new UnsupportedOperationException();
  9.     }
  10.     // 默认行为:叶子结点禁止新增元素
  11.     public void addChild(HTMLElement element) {
  12.         throw new UnsupportedOperationException();
  13.     }
  14.     // 默认行为:叶子结点禁止移除子元素
  15.     public void removeChild(HTMLElement element) {
  16.         throw new UnsupportedOperationException();
  17.     }
  18.     // 辅助方法:生成缩进
  19.     protected String generateIndent(int level) {
  20.         StringBuilder indent = new StringBuilder();
  21.         for (int i = 0; i < level * 2; i++) {
  22.             indent.append(" "); // 每层缩进2个空格
  23.         }
  24.         return indent.toString();
  25.     }
  26. }
复制代码
2. 组合结点

表示可以包含子元素的HTML标签
  1. public class HTMLComposite extends HTMLElement {
  2.     private List<HTMLElement> children = new LinkedList<>();
  3.     public HTMLComposite(String name) {
  4.         super(name);
  5.     }
  6.     @Override
  7.     public void addChild(HTMLElement element) {
  8.         children.add(element);
  9.     }
  10.     @Override
  11.     public void removeChild(HTMLElement element) {
  12.         children.remove(element);
  13.     }
  14.     @Override
  15.     public HTMLElement getChild(int index) {
  16.         return children.get(index);
  17.     }
  18.     @Override
  19.     public void render(int level) {
  20.         System.out.println(generateIndent(level) + "<" + name + ">");
  21.         for (HTMLElement child : children) {
  22.             child.render(level + 1); // 子节点递归调用
  23.         }
  24.         System.out.println(generateIndent(level) + "</" + name + ">");
  25.     }
  26. }
复制代码
3.叶子节点

表示没有子元素的HTML标签
  1. public class HTMLLeaf extends HTMLElement {
  2.     public HTMLLeaf(String name) {
  3.         super(name);
  4.     }
  5.     @Override
  6.     public void render(int level) {
  7.         System.out.println(generateIndent(level) + "<" + name + " />");
  8.     }
  9. }
复制代码
测试
  1. public class CompositePatternHTMLDemo {
  2.     public static void main(String[] args) {
  3.         // 创建HTML结构
  4.         HTMLElement html = new HTMLComposite("html");
  5.         HTMLElement body = new HTMLComposite("body");
  6.         HTMLElement div = new HTMLComposite("div");
  7.         HTMLElement img = new HTMLLeaf("img");
  8.         HTMLElement input = new HTMLLeaf("input");
  9.         HTMLElement p = new HTMLLeaf("p");
  10.         // 组合结构
  11.         html.addChild(body);
  12.         body.addChild(div);
  13.         body.addChild(input);
  14.         div.addChild(img);
  15.         div.addChild(p);
  16.         // 渲染HTML结构
  17.         html.render(0);
  18.         // 去除某个节点
  19.         div.removeChild(p);
  20.         html.render(0);
  21.     }
  22. }
复制代码
测试结果:
  1. <html>
  2.   <body>
  3.    
  4.       <img />
  5.       <p />
  6.    
  7.     <input />
  8.   </body>
  9. </html>
  10. <html>
  11.   <body>
  12.    
  13.       <img />
  14.    
  15.     <input />
  16.   </body>
  17. </html>
复制代码
从类图或测试类(使用者)中可以看出,使用者直接依赖于具体的类,属于高耦合的一种编程方式。
简单优化(结合其它设计模式)

加入一个工厂类来创建组合节点和叶子结点
类图结构变为
2.png

工厂类代码
[code]public class HTMLElementFactory {    private static Map
您需要登录后才可以回帖 登录 | 立即注册