掌握设计模式--组合模式
组合模式(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]