组合模式(Composite)属于结构性模式,它描述了对象间的组合关系。
对象间常常通过树结构来组织(包含)起来,以实现整体-部分的层次结构。整体上可以看做是一个组合对象。
抛却各种复杂的术语,组合模式的特点是:
对象通过实现(继承)统一的接口(抽象类),调用者对单一对象和组合对象的操作具有一致性。
组合模式很常见,Java的容器类(比如ArrayList)都实现了组合模式。
我们平常操作最多的文件(夹)就是组合模式的最好例子。文件系统是树形层次结构,并且文件和文件夹提供给用户的一些操作是相同的,比如复制。于是,可以通过一个统一的接口将文件和文件夹统一起来,对用户提供一致的操作,屏蔽不同的复制实现过程。我们在复制文件夹的时候,操作系统实现了对文件夹内的所有文件和文件夹的复制,即实现了组合对象的整体复制,而不是一个空的文件夹;这和我们复制单个文件的体验是一致的。这便是组合模式的妙处。
“将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。”
定义(GoF《设计模式》):将对象组合成树形结构以表示“部分整体”的层次结构。组合模式使得用户对单个对象和使用具有一致性。
涉及角色:
1.Component 是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component
子部件。
2.Leaf 在组合中表示叶子结点对象,叶子结点没有子结点。
3.Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除
(remove)等。
适用性
以下情况下适用Composite模式:
1.你想表示对象的部分-整体层次结构
2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
例如:上学的时候的背课文,我记得那个时候老师太忙或者想偷懒的时候,就会给我们说,班长负责监督组长的背课文任务,组长,监督组员的,班长向我背课文。
这就是很明显的属性结构,班长下面有N个组长,组长下面有N个组员。代码实现如下:
全部实现背课文的接口
package com.java.compent; public interface classroom { public void speakbook(String name);//背课文 //管理各个类 public void add(classroom cl); public void remove(classroom cl); }
package com.java.compent; import java.util.ArrayList; public class classManager implements classroom { ArrayList<classroom> arr = new ArrayList<classroom>(); String name; public classManager(String name) { this.name = name; } @Override public void speakbook(String name) { System.out.println("我是" + this.name + "," + "我直接向" + name + "背课文!"); for (classroom classroom : arr) { classroom.speakbook(this.name); } } @Override public void add(classroom cl) { // TODO Auto-generated method stub arr.add(cl); } @Override public void remove(classroom cl) { // TODO Auto-generated method stub arr.remove(cl); } }
package com.java.compent; public class nomalStudent implements classroom { String name; public nomalStudent(String name) { this.name = name; } @Override public void speakbook(String name) { System.out.println("我是" + this.name + "," + "我向" + name + "背书!"); } @Override public void add(classroom cl) { } @Override public void remove(classroom cl) { } }
package com.java.compent; public class TestCompent { public static void main(String[] args) { classroom cm = new classManager("班长"); classManager ec1 = new classManager("组长1"); classManager ec2 = new classManager("组长2"); classManager ec3 = new classManager("组长3"); cm.add(ec1); cm.add(ec2); cm.add(ec3); nomalStudent ns1 = new nomalStudent(" 普通学生1"); nomalStudent ns2 = new nomalStudent(" 普通学生2"); nomalStudent ns3 = new nomalStudent(" 普通学生3"); nomalStudent ns4 = new nomalStudent(" 普通学生4"); ec1.add(ns1); ec1.add(ns2); ec2.add(ns3); ec2.add(ns4); cm.speakbook("火影"); } }运行结果:
我是班长,我直接向火影背课文!
我是组长1,我直接向班长背课文!
我是 普通学生1,我向组长1背书!
我是 普通学生2,我向组长1背书!
我是组长2,我直接向班长背课文!
我是 普通学生3,我向组长2背书!
我是 普通学生4,我向组长2背书!
我是组长3,我直接向班长背课文!