定义
Composite模式是一种结构型设计模式,它将对象组合成树形结构以表示“部分-整体“的层次结构,并使用户对单个对象和组合对象的使用具有一致性。
动机
当处理树形结构的数据时,我们常常需要区别对待叶子结点和内部结点,这使得代码更加复杂,以至于容易出错。因此,如果有一种方法,可以使我们可以统一处理叶子结点和内部结点,那么,对于我们提高代码的质量是十分有帮助的。
Composite模式正是这样一种设计模式,它可以使我们以统一的方式去处理叶子结点(单个对象)和内部结点(组合对象)。
适用性
当你想表示“部分-整体“的层次结构,并希望忽略组合对象和单个对象不同,可以使用统一的方式来处理组合结构中的所有对象。
结构
Compenent
- 所有对象的抽象,包括组合对象和单个对象
- 声明对象的接口
Leaf
- 表示单个对象
- 实现所有的Compent接口
Composite
- 代表组合对象
- 实现所有的Compent接口
- 还包括了对其孩子对象进行操作的接口
例子
在下面的例子中,我们实例一个图形系统。图形可以是椭圆(Ellipse)或者复合图形(CompositeGraphic),每个图形都可以打印出来,打印接口在Graphic接口中声明。
这个图形系统是易于扩展的,例如加入矩形,圆形等,也可以加入其他的方法,例如缩放等。
Graphic.java
/** "Component" */
interface Graphic {
// Prints the graphic.
public void print();
}
CompositeGraphic.java
/** "Composite" */
import java.util.List;
import java.util.ArrayList;
class CompositeGraphic implements Graphic {
// Collection of child graphics.
private List<Graphic> childGraphics = new ArrayList<Graphic>();
// Prints the graphic.
public void print() {
for (Graphic graphic : childGraphics) {
graphic.print();
}
}
// Adds the graphic to the composition.
public void add(Graphic graphic) {
childGraphics.add(graphic);
}
// Removes the graphic from the composition.
public void remove(Graphic graphic) {
childGraphics.remove(graphic);
}
}
Ellipse.java
/** "Leaf" */
class Ellipse implements Graphic {
// Prints the graphic.
public void print() {
System.out.println("Ellipse");
}
}
最后是使用这套图形系统的测试程序。它首先初始化4个椭圆(ellipse1, ellipse2, ellipse3, ellipse4),然后构造2个复合图形(graphic1, graphic2),再使用这2个复合图形来构造一个复合图形(graphic),最后使用Graphic接口(print)来将graphic图形打印出来:
Program.java
/** Client */
public class Program {
public static void main(String[] args) {
// Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
// Initialize three composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
// Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(graphic1);
graphic.add(graphic2);
// Prints the complete graphic (four times the string "Ellipse").
graphic.print();
}
}
输出:
Ellipse
Ellipse
Ellipse
Ellipse