组合模式又称合成模式,国外设计模式大师GOF把合成模式定义为:“将对象组合成树形结构以表示” 部分-整体的 层次结构
“将对象组合成树形结构以表示” 部分-整体的 层次结构可以理解为“通过树形结构,同等显示多个独立的对象以及他们复合而成的合成对象”
1.结构
Component:为组合中的对象声明接口。在适当的情况下,嘻嘻所有类共有接口的缺省行为,声明一个接口用户访问和管理Component的只组件。在递归结构中定义一个接口(可选),用户访问一个父部件并在合适的情况下实现它
Leaf:在组合中表示叶借点对象,叶子点没有子节点对,在组合定义图元对的行为
Composite:定义有子部件的那些部件的行为,存储子部件,在Component接口中实现与子部件有关的操作
Client:通过Component接口操纵组合部件的对象
2.实例
人事管理系统是Componet
员工原理包括 员工列表、新增员工、修改员工、员工资料上传、员工查询 子菜单(即没有内部树结构),因此,它只是一种树叶节点(即leaf)
以上树节点和树叶根据相同的地位共同组合人事管理系统,这就是组合模式在实际软件开发中的一个现实案例
应用优势与时机
组合具备以下一些优势
1.树型结构抑郁增加组合对象
2.无论分层对象是否复杂,均可清晰定义,并且可方便的添加新的构件
3.客户端可简便的共同调用组合或单个对象
应用场景
当开发树形结构系统时
当客户要求软件需要展现全局与个体关系时
当系统需要共同使用组合结构的全体对象时
示例
package model.composite;
/*
* 排级单位抽象类
* 定义一个军队排级单位的抽象类-即Component
*/
public abstract class Group {
private String name = "";//姓名
private String post = "";//官职
private String no = "";//编号
private Group parent = null;
//实际软件项目中构造函数的定义
public Group(String name, String post, String no) {
super();
this.name = name;
this.post = post;
this.no = no;
}
//获取军官信息
public String getMessage(){
String message ="";
message ="姓名:"+this.name;
message = message + "\t官职:"+this.post;
message = message + "\t编号:"+this.no;
return message;
}
//获取父节点
public Group getParent() {
return parent;
}
//设置父节点
public void setParent(Group parent) {
this.parent = parent;
}
}
package model.composite;
/*
* 叶子类
* 班长-无下属军官的军官-Leaf
*/
public class Monitor extends Group{
public Monitor(String name, String post, String no) {
super(name, post, no);
}
}
package model.composite;
import java.util.ArrayList;
/*
* 节点类
*/
public class Node extends Group {
//构造函数的定义
public Node(String name, String post, String no) {
super(name, post, no);
}
//上机军官下属包括哪些下级军官和下下级军官
ArrayList<Group> juniorList = new ArrayList<Group>();
//增加一个下属,可能是下级军官,也可能是个下下级军官
public void addJunior(Group group){
group.setParent(this);
juniorList.add(group);
}
//上级拥有的下属
public ArrayList<Group> getJunior(){
return this.juniorList;
}
}
package model.composite;
import java.util.ArrayList;
/*
* 客户端测试类
* 展现属树型结构:
* 一级节点是排长platoonOfficer ,二级节点是副排长platoonSergeant,三级节点是班长monitor
*/
public class ClientCase {
/*
* 实现树型结构
*/
public static Node CompositeNodeTree(){
//一级节点
Node node = new Node("杰克", "排长", "A0001");
//二级节点:二个副排长
Node platoonSergeant1 = new Node("李东", "副排长", "A0002");
Node platoonSergeant2 = new Node("将飞", "副排长", "A0003");
//三级节点:班长
Monitor a0002_1 = new Monitor("陈小小", "班长", "A0002_1");
Monitor a0002_2 = new Monitor("李梅", "班长", "A0002_2");
Monitor a0002_3 = new Monitor("师徒青云", "班长", "A0002_3");
Monitor a0003_1 = new Monitor("金宏", "班长", "A0003_1");
Monitor a0003_2 = new Monitor("马晓宇", "班长", "A0003_2");
Monitor a0003_3 = new Monitor("林东桥", "班长", "A0003_3");
//设置下级-----------------
//排长下属二个副排长
node.addJunior(platoonSergeant1);
node.addJunior(platoonSergeant2);
//两个副排长下的下属
platoonSergeant1.addJunior(a0002_1);
platoonSergeant1.addJunior(a0002_2);
platoonSergeant1.addJunior(a0002_3);
platoonSergeant2.addJunior(a0003_1);
platoonSergeant2.addJunior(a0003_2);
platoonSergeant2.addJunior(a0003_3);
return node;
}
/*
*使用递归的方式通过根节点,遍历出所有的节点
*/
public static String getTreeMessage(Node node){
ArrayList<Group> juniorList = node.juniorList;
String message = "";
for (Group group : juniorList) {
if(group instanceof Monitor){
message = message + group.getMessage()+"\n";
}else{
message = message + group.getMessage() + "\n" +getTreeMessage((Node)group);
}
}
return message;
}
//打印显示信息
public static void main(String[] args) {
Node node = CompositeNodeTree();
//一级节点-排长
System.out.println(node.getMessage());
//所有军官信息
System.out.println(getTreeMessage(node));
}
}