又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。
什么时候用?
1、你想表示对象的部分-整体层次关系(树形结构)
2、您希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
组合模式与之前讲的装饰器模式很像,都是通过在类中存储成员变量来完成一些功能上的扩展,那么它们之间有什么不同呢?
- 每一个装饰器类只有含有一个组件,即没有对象聚合,而每个组合类可以含有多个组件,即 Composite。
- 装饰器模式倾向于在原有对象的基础上添加新的功能,组合模式倾向于对原有对象的功能进行组合使用。
业务场景?
考虑下面的场景:
你被要求开发一个简单的图形库。初始要求是:
- 图形库必须能够处理基础图形,如线和圆。
- 图形库必须允许复合和基础图形的递归复合,以便绘图可以由多种图形组成。
- 需要提供操作以允许添加,移除,显示和图形组件。
思路很清晰,图形分为基础图形和组合图形,用组合模式再合适不过了。
用 Java 代码表示:
基础图形:
abstract class GraphicsObject {
public abstract void draw();
public void add(GraphicsObject object) {
throw new UnsupportedOperationException();
}
public void remove(GraphicsObject object) {
throw new UnsupportedOperationException();
}
}
class Circle extends GraphicsObject {
public void draw() {
System.out.println("draw circle");
}
}
class Line extends GraphicsObject {
public void draw() {
System.out.println("draw line");
}
}
class Rectangle extends GraphicsObject {
public void draw() {
System.out.println("draw rectangle");
}
}
组合图形:
import java.util.ArrayList;
class ComposedGraphicsObject extends GraphicsObject {
private ArrayList<GraphicsObject> components;
public ComposedGraphicsObject() {
components = new ArrayList<GraphicsObject>();
}
@Override
public void add(GraphicsObject object) {
components.add(object);
}
@Override
public void remove(GraphicsObject object) {
components.remove(object);
}
public void draw() {
for(GraphicsObject component: components) {
component.draw();
}
}
}
图形库:
import java.util.ArrayList;
class GraphicsLibrary {
private ArrayList<GraphicsObject> components;
public GraphicsLibrary() {
components = new ArrayList<GraphicsObject>();
initData();
}
public void initData() {
GraphicsObject line = new Line();
GraphicsObject circle = new Circle();
GraphicsObject rectangle = new Rectangle();
//添加基础图形到图形库中
components.add(line);
components.add(circle);
components.add(rectangle);
//创建并添加组合图形到图形库中
GraphicsObject composite = new ComposedGraphicsObject();
composite.add(line);
composite.add(rectangle);
components.add(composite);
}
public ArrayList<GraphicsObject> getGraphicsObjects() {
return components;
}
}
客户端调用:
class Client {
public static void main(String[] args) {
GraphicsLibrary gl = new GraphicsLibrary();
//使用基础图形 line
System.out.println("第一个图形:");
gl.getGraphicsObjects().get(0).draw();
//使用组合图形 composite
System.out.println("第二个图形:");
gl.getGraphicsObjects().get(3).draw();
}
}