睁扼妤 发表于 2025-6-6 14:10:09

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

组合模式(Composite Pattern)

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


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


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

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

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


1. 抽象组件

HTML顶层元素抽象类。你也可以定义一个顶层接口,然后在抽象类中实现基础功能。
public abstract class HTMLElement {
    protected String name;

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

    public abstract void render(int level);

    public HTMLElement getChild(int index) {
      throw new UnsupportedOperationException();
    }

    // 默认行为:叶子结点禁止新增元素
    public void addChild(HTMLElement element) {
      throw new UnsupportedOperationException();
    }
    // 默认行为:叶子结点禁止移除子元素
    public void removeChild(HTMLElement element) {
      throw new UnsupportedOperationException();
    }

    // 辅助方法:生成缩进
    protected String generateIndent(int level) {
      StringBuilder indent = new StringBuilder();
      for (int i = 0; i < level * 2; i++) {
            indent.append(" "); // 每层缩进2个空格
      }
      return indent.toString();
    }
}2. 组合结点

表示可以包含子元素的HTML标签
public class HTMLComposite extends HTMLElement {
    private List<HTMLElement> children = new LinkedList<>();

    public HTMLComposite(String name) {
      super(name);
    }

    @Override
    public void addChild(HTMLElement element) {
      children.add(element);
    }

    @Override
    public void removeChild(HTMLElement element) {
      children.remove(element);
    }

    @Override
    public HTMLElement getChild(int index) {
      return children.get(index);
    }

    @Override
    public void render(int level) {
      System.out.println(generateIndent(level) + "<" + name + ">");
      for (HTMLElement child : children) {
            child.render(level + 1); // 子节点递归调用
      }
      System.out.println(generateIndent(level) + "</" + name + ">");
    }
}3.叶子节点

表示没有子元素的HTML标签
public class HTMLLeaf extends HTMLElement {
    public HTMLLeaf(String name) {
      super(name);
    }

    @Override
    public void render(int level) {
      System.out.println(generateIndent(level) + "<" + name + " />");
    }
}测试

public class CompositePatternHTMLDemo {
    public static void main(String[] args) {
      // 创建HTML结构
      HTMLElement html = new HTMLComposite("html");
      HTMLElement body = new HTMLComposite("body");
      HTMLElement div = new HTMLComposite("div");
      HTMLElement img = new HTMLLeaf("img");
      HTMLElement input = new HTMLLeaf("input");
      HTMLElement p = new HTMLLeaf("p");


      // 组合结构
      html.addChild(body);
      body.addChild(div);
      body.addChild(input);
      div.addChild(img);
      div.addChild(p);

      // 渲染HTML结构
      html.render(0);

      // 去除某个节点
      div.removeChild(p);
      html.render(0);
    }
}测试结果:
<html>
<body>
   
      <img />
      <p />
   
    <input />
</body>
</html>
<html>
<body>
   
      <img />
   
    <input />
</body>
</html>从类图或测试类(使用者)中可以看出,使用者直接依赖于具体的类,属于高耦合的一种编程方式。
简单优化(结合其它设计模式)

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

工厂类代码
public class HTMLElementFactory {    private static Map
页: [1]
查看完整版本: 掌握设计模式--组合模式