一、简介
组合模式是一种结构型设计模式,它允许你将对象组合成树形结构以表示“整体-部分”的层次结构。组合模式使得客户端对单个对象和组合对象的处理具有一致性,可以像处理单个对象一样来处理组合对象。在组合模式中,有两种主要类型的对象:
- 叶子(Leaf): 叶子是组合结构的最底层对象,它没有子元素。它实现了组合中的统一接口,但是不包含其他子对象。
- 组合(Composite): 组合是包含子元素的对象。它也实现了统一的接口,但是除了执行基本操作外,它还能管理其子元素。
这种模式使得客户端可以递归地处理单个对象和组合对象,而无需了解处理的是哪种类型的对象。
组合模式通常用于以下情况:
- 需要表示对象的整体-部分层次结构。
- 希望用户统一地对待单个对象和组合对象。
- 希望能够以相同的方式处理单个对象和组合对象,而不需要进行类型检查。
总而言之,组合模式允许你创建树形结构,其中叶子和组合对象都实现了相同的接口,并且可以递归地进行处理。这种设计模式使得代码更具扩展性,允许以统一的方式处理对象集合的层次结构。
二、图形界面
其实组合模式到处可见,工作中你用到了都没在意过,比如树形菜单、文件系统中,文件和文件夹等。
2.1、统一组件接口
我们这里定义一个组件接口
// 统一的组件接口
public interface UIComponent {
void draw();
}
2.2、叶子节点
我们有文本框和按钮两个组件实现了上述的接口。
// 输入框组件:文本框
public class TextBox implements UIComponent {
private String placeholder;
public TextBox(String placeholder) {
this.placeholder = placeholder;
}
public void draw() {
System.out.println("开始画一个输入框: " + placeholder);
}
}
// 叶子节点:按钮
public class Button implements UIComponent {
private String label;
public Button(String label) {
this.label = label;
}
public void draw() {
System.out.println("开始画一个按钮: " + label);
}
}
2.3、组合节点
我们组合节点面板也实现了组件接口,然后它持有其他组件的列表,并且提供相应添加、删除接口。
import java.util.ArrayList;
import java.util.List;
// 组合节点:面板
public class Panel implements UIComponent {
private String title;
private List<UIComponent> components;
public Panel(String title) {
this.title=title;
this.components = new ArrayList<>();
}
public void addComponent(UIComponent component) {
components.add(component);
}
public void removeComponent(UIComponent component) {
components.remove(component);
}
public void draw() {
System.out.println("开始画一个面板:");
for (UIComponent component : components) {
component.draw();
}
}
}
2.4、使用
测试代码如下:
public class UIClient {
public static void main(String[] args) {
// 创建输入框
TextBox textBox = new TextBox("Enter your name");
// 创建按钮
Button btn1 = new Button("提交");
Button btn2 = new Button("取消");
// 创建面板并添加按钮和输入框
Panel panel = new Panel("意见反馈");
panel.addComponent(textBox);
panel.addComponent(btn1);
panel.addComponent(btn2);
// 绘制整个界面
panel.draw();
}
}
运行结果:
开始画一个面板:
开始画一个输入框: Enter your name
开始画一个按钮: 提交
开始画一个按钮: 取消
2.5、优缺点
组合模式的优点和缺点如下:
优点:
- 统一性: 该模式使得客户端代码可以统一地处理单个对象和组合对象,无需区分操作对象的类型。
- 灵活性: 可以在组合结构中添加或移除对象,无需修改现有代码,使得系统更加灵活、可扩展。
- 简化客户端代码: 使用组合模式,客户端代码更简洁清晰,无需过多的条件判断逻辑,提高代码可读性。
- 易于扩展: 方便地增加新类型的对象,通过继承组合模式中的抽象类或实现统一接口即可。
缺点:
- 限制类型: 因为组合模式统一了叶子和组合对象,可能导致一些限制。例如,对于叶子对象来说,如果某些方法在它们身上没有意义,就需要对这些方法进行空实现或者抛出异常。
- 难以限制组合中的元素类型: 在某些情况下,可能需要限制组合中包含的对象类型,而组合模式难以提供这样的限制。
- 可能带来过多的一般性设计: 对于简单的情况,使用组合模式可能带来过多的抽象,增加了设计的一般性,使得系统变得过于复杂。
虽然组合模式有一些缺点,但在合适的情况下,通过提供统一的接口来处理对象的整体-部分结构,组合模式可以使得代码更加清晰、灵活,并且更易于扩展,所以相比继承我更推荐组合模式。