组合模式( Composite Pattern)

参考文档:http://blog.csdn.net/ai92/article/details/298336

定义:

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


设计动机:


这幅图片我们都可以看做是一个文件结构,对于这样的结构我们称之为树形结构。在数据结构中我们了解到可以通过调用某个方法来遍历整个树,当我们找到某个叶子节点后,就可以对叶子节点进行相关的操作。我们可以将这颗树理解成一个大的容器,容器里面包含很多的成员对象,这些成员对象即可是容器对象也可以是叶子对象。但是由于容器对象和叶子对象在功能上面的区别,使得我们在使用的过程中必须要区分容器对象和叶子对象,但是这样就会给客户带来不必要的麻烦,作为客户而已,它始终希望能够一致的对待容器对象和叶子对象。这就是组合模式的设计动机:组合模式定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。


模式实现:

  • Component:抽象构件角色。它为组合中的对象声明接口,也可以为共有接口实现缺省行为
  • Leaf:树叶构件角色。在组合中表示叶节点对象——没有子节点,实现抽象构件角色声明的接口。

  • Composite:树枝构件角色。在组合中表示分支节点对象——有子节点,实现抽象构件角色声明的接口;存储子部件。

     

     一种方式是在Component里面声明所有的用来管理子类对象的方法,以达到Component接口的最大化(如下图所示)。目的就是为了使客户看来在接口层次上树叶和分支没有区别——透明性。但树叶是不存在子类的,因此Component声明的一些方法对于树叶来说是不适用的。这样也就带来了一些安全性问题。




      另一种方式就是只在Composite里面声明所有的用来管理子类对象的方法(如下图所示)。这样就避免了上一种方式的安全性问题,但是由于叶子和分支有不同的接口,所以又失去了透明性。

  《设计模式》一书认为:在这一模式中,相对于安全性,我们比较强调透明性。对于第一种方式中叶子节点内不需要的方法可以使用空处理或者异常报告的方式来解决。


优点:

      1、可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,使得增加新构件也更容易。

      2、客户端调用简单,客户端可以一致的使用组合结构或其中单个对象。

      3、定义了包含叶子对象和容器对象的类层次结构,叶子对象可以被组合成更复杂的容器对象,而这个容器对象又可以被组合,这样不断递归下去,可以形成复杂的树形结构。

      4、更容易在组合体内加入对象构件,客户端不必因为加入了新的对象构件而更改原有代码。

举个栗子:

 定义抽象角色

abstract class File{
    public abstract void addChild(File f);
    public abstract void delChild(File f);
    public abstract void scan();
}

 定义叶子实现

class ImgFile extends File{
    @Override
    public void addChild(File f) {
    }
    @Override
    public void delChild(File f) {
    }
    @Override
    public void scan() {
        System.out.println("im an img");
    }
}

 定义叶子实现

    class VideoFile extends File{  
        @Override  
        public void addChild(File f) {  
        }  
        @Override  
        public void delChild(File f) {  
        }  
        @Override  
        public void scan() {  
            System.out.println("im a video");  
        }  
    }  

定义树枝实现

    class Folder extends File{  
        List<File> files=new ArrayList<File>();  
        @Override  
        public void addChild(File f) {  
            files.add(f);  
        }  
        @Override  
        public void delChild(File f) {  
            files.remove(f);          
        }  
        @Override  
        public void scan() {  
            System.out.println("im folder,i have some files :");  
            for (File f : files) {  
                f.scan();  
            }  
        }  
    }  

客户端调用

    public static void main(String[] args) {  
          File c=new Folder();  
          File windows=new  Folder();  
          windows.addChild(new ImgFile());  
          c.addChild(windows);  
          c.scan();  
        }  
原文地址:https://www.cnblogs.com/amei0/p/7929949.html