设计模式-组合模式
组合模式是一种结构型设计模式,用于将对象组成树形结构,以表示部分整体的层次结构。这种模式创建了一个包含自己对象组的类。这些对象被称为Leaf和Composite。 Leaf表示树的叶节点,而Composite表示树的枝节点。该模式通过实现一个公共接口使得所有节点都可以被一致的方式处理。
组合模式的适用情况:
1. 当需要创建可供用户自由组合的对象树时。
2. 需要在树中管理对象的层次结构时。
3. 希望表示对象部分和整体的层次结构。
4. 希望客户端能够忽略组合对象与单个对象之间的差异,一致地处理二者。
组合模式的结构图如下:

此图有一个基本组件Component,其中定义了组合操作的接口。Leaf 定义了组合中叶节点的行为,Composite 定义了组合中分支节点的行为,同时包含了 Leaf 组件。
通过一个示例来了解组合模式是如何使用的。
假设现在我们需要创建一个品牌广告栏目的网站。
品牌广告的展示形式分为横幅广告(Banner), 浮窗广告(Popup),视频广告(Video)。
首先需要定义一个基本组件 Component 用于组合接口,其中包含了增、删、遍历等方法:
public interface Component {
public void add(Component c);
public void remove(Component c);
public void display(int depth);
}
然后定义两个分支节点 Banner 和 Video
public class Banner implements Component {
private String name;
public Banner(String name) {
this.name = name;
}
@Override
public void add(Component c) {
System.out.println("Cannot add to a single banner");
}
@Override
public void remove(Component c) {
System.out.println("Cannot remove from a single banner");
}
@Override
public void display(int depth) {
System.out.println(String.format("%s%s", String.join("", Collections.nCopies(depth, "-")), this.name));
}
}
public class Video implements Component {
private String name;
public Video(String name) {
this.name = name;
}
@Override
public void add(Component c) {
System.out.println("Cannot add to a single video");
}
@Override
public void remove(Component c) {
System.out.println("Cannot remove from a single video");
}
@Override
public void display(int depth) {
System.out.println(String.format("%s%s", String.join("", Collections.nCopies(depth, "-")), this.name));
}
}
最后定义一个浮窗广告( Popup), 用集合储存多个横幅广告与视频广告,用add方法加入和删除广告.
public class Popup implements Component {
private String name;
private List<Component> components = new ArrayList<>();
public Popup(String name) {
this.name = name;
}
@Override
public void add(Component c) {
components.add(c);
}
@Override
public void remove(Component c) {
components.remove(c);
}
@Override
public void display(int depth) {
System.out.println(String.format("%s%s", String.join("", Collections.nCopies(depth, "-")), this.name));
for (Component component : components) {
component.display(depth + 2);
}
}
}
最后我们在测试类中进行测试,输出结果如下:

通过组合模式,我们可以方便地管理多棵不同结构的树形结构,并简化了客户端的调用。 您可以通过添加新分支节点或叶节点来扩展广告栏目缺省类型,在客户端无需修改任何代码的情况下创建计算机,减少编写代码和维护代码的工作量。总之, 组合模式是一种用途非常广泛的设计模式,在实际项目中,使用此模式可以更好地管理对象的层次结构,简化代码,并提高代码的可维护性。
