目录

组合模式

Composite

定义

组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次。

它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。

最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。

虽然组合模式能够清晰地定义分层次的复杂对象,也使得增加新构件也更容易,但是这样就导致了系统的设计变得更加抽象,如果系统的业务规则比较复杂的话,使用组合模式就有一定的挑战了。

参与者:

  • Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
  • Leaf:叶子对象。叶子结点没有子结点。
  • Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。

组合模式的分类

将管理子元素的方法定义在Composite类中 将管理子元素的方法定义在Componen接口中,这样Leaf类就需要对这些方法空实现。

实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public abstract class File {
    String name;    
    public File(String name){
        this.name = name;
    }    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public abstract void display();
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
public class Folder extends File{
    private List<File> files;
    
    public Folder(String name){
        super(name);
        files = new ArrayList<File>();
    }
    public void display() {
        for(File file : files){
            file.display();
        }
    }
    public void add(File file){
        files.add(file);
    }
    public void remove(File file){
        files.remove(file);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class TextFile extends File{
    public TextFile(String name) {
        super(name);
    }
    public void display() {
        System.out.println("这是文本文件,文件名:" + super.getName());
    }    
}
public class ImagerFile extends File{
    public ImagerFile(String name) {
        super(name);
    }
    public void display() {
        System.out.println("这是图像文件,文件名:" + super.getName());
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
public class Client {
    public static void main(String[] args) {
        Folder zwjj = new Folder("总文件夹");
        TextFile aText= new TextFile("a.txt");
        ImagerFile bImager = new ImagerFile("b.jpg");
        Folder cFolder = new Folder("C文件夹");
        
        zwjj.add(aText);
        zwjj.add(bImager);
        zwjj.add(cFolder);
        
        TextFile cText = new TextFile("c_1.txt");        
        cFolder.add(cText);        
        zwjj.display();
    }
}

优缺点

优点

  • 可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。
  • 客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。
  • 定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。
  • 更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

缺点

  • 使设计变得更加抽象,对象的业务规则如果很复杂,则实现组合模式具有很大挑战性,而且不是所有的方法都与叶子对象子类都有关联

使用场景

  • 需要表示一个对象整体或部分层次,在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,可以一致地对待它们。
  • 让客户能够忽略不同对象层次的变化,客户端可以针对抽象构件编程,无须关心对象层次结构的细节。

总结

  • 组合模式用于将多个对象组合成树形结构以表示“整体-部分”的结构层次。组合模式对单个对象(叶子对象)和组合对象(容器对象)的使用具有一致性。

  • 组合对象的关键在于它定义了一个抽象构建类,它既可表示叶子对象,也可表示容器对象,客户仅仅需要针对这个抽象构建进行编程,无须知道他是叶子对象还是容器对象,都是一致对待。

  • 组合模式虽然能够非常好地处理层次结构,也使得客户端程序变得简单,但是它也使得设计变得更加抽象,而且也很难对容器中的构件类型进行限制,这会导致在增加新的构件时会产生一些问题。