一、概述
组合模式,又叫部分整体模式,属于结构型模式,它创建了对象组的属性结构,将对象组合成树状结构以表示“整体-部分”的层次关系。组合模式可以不提供父对象的管理方法,但是组合模式必须在合适的地方提供子对象的管理方法,例如:add(),remove()以及getChild()等。组合模式的实现根据所实现接口的区别分为安全式和透明式。
二、角色
抽象构件(Component):定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性
树枝构件(Composite):树枝对象,用于存储子部件,在Component接口中实现子部件的相关操作,比如增加,删除
叶子构件(Leaf):叶子对象,其下再也没有其他的分支,也就是遍历的最小单位
三、组合模式
1.安全式组合模式
安全模式的组合模式要求管理聚集的方法只出现在树枝构件类中,而不出现树叶构件类中
1) 抽象构件
public interface OrganizationComponent {
void print();
}
2) 树枝构件
// University就是Composite
public class University implements OrganizationComponent {
private String name;
// 存放的是College
private List<OrganizationComponent> organizationComponents = new ArrayList<>();
public University(String name) {
this.name = name;
}
public void addChild(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
public void removeChild(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
// 输入University所包含的College
@Override
public void print() {
System.out.println("- - - -" + name + "- - - -");
// 遍历organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
public class College implements OrganizationComponent {
private String name;
// 存放的是Department
private List<OrganizationComponent> organizationComponents = new ArrayList<>();
public College(String name) {
this.name = name;
}
public void addChild(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
public void removeChild(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
// 输入College所包含的Department
@Override
public void print() {
System.out.println("- - - -" + name + "- - - -");
// 遍历organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
3) 叶子构件
public class Department implements OrganizationComponent {
private String name;
public Department(String name) {
this.name = name;
}
public void print() {
System.out.println(name);
}
}
4) 使用
@Test
public void testSafeComposite() {
// 创建学校
University university = new University("清华大学");
// 创建学院
College computerCollege = new College("计算机学院");
College infoEngineerCollege = new College("信息工程学院");
// 创建系
computerCollege.addChild(new Department("软件工程"));
computerCollege.addChild(new Department("网络工程"));
computerCollege.addChild(new Department("计算机科学与技术"));
infoEngineerCollege.addChild(new Department("通信工程"));
infoEngineerCollege.addChild(new Department("信息工程"));
university.addChild(computerCollege);
university.addChild(infoEngineerCollege);
university.print();
}
2.透明式组合模式
透明式的组合模式要求所有的具体构件类,不论数构件还是树叶构件,均符合一个固定接口
1) 抽象构件
public abstract class OrganizationComponent {
private String name;
public OrganizationComponent(String name) {
this.name = name;
}
protected void removeChild(OrganizationComponent organizationComponent) {
// 默认实现
throw new UnsupportedOperationException();
}
protected void addChild(OrganizationComponent organizationComponent) {
// 默认实现
throw new UnsupportedOperationException();
}
protected abstract void print();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2) 树枝构件
public class University extends OrganizationComponent {
// 存放的是College
private List<OrganizationComponent> organizationComponents = new ArrayList<>();
// 构造器
public University(String name) {
super(name);
}
@Override
protected void addChild(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void removeChild(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
// 输入University所包含的College
@Override
protected void print() {
System.out.println("- - - -" + getName() + "- - - -");
// 遍历organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
public class College extends OrganizationComponent {
// 存放的是Department
private List<OrganizationComponent> organizationComponents = new ArrayList<>();
// 构造器
public College(String name) {
super(name);
}
@Override
protected void addChild(OrganizationComponent organizationComponent) {
organizationComponents.add(organizationComponent);
}
@Override
protected void removeChild(OrganizationComponent organizationComponent) {
organizationComponents.remove(organizationComponent);
}
// 输入College所包含的Department
@Override
protected void print() {
System.out.println("- - - -" + getName() + "- - - -");
// 遍历organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
3) 叶子构件
public class Department extends OrganizationComponent {
public Department(String name) {
super(name);
}
// add,remove就不用写了,因为它是叶子节点
@Override
protected void print() {
System.out.println(getName());
}
}
4) 使用
@Test
public void testComposite() {
// 创建学校
OrganizationComponent university = new University("清华大学");
// 创建学院
OrganizationComponent computerCollege = new College("计算机学院");
OrganizationComponent infoEngineerCollege = new College("信息工程学院");
// 创建系
computerCollege.addChild(new Department("软件工程"));
computerCollege.addChild(new Department("网络工程"));
computerCollege.addChild(new Department("计算机科学与技术"));
infoEngineerCollege.addChild(new Department("通信工程"));
infoEngineerCollege.addChild(new Department("信息工程"));
university.addChild(computerCollege);
university.addChild(infoEngineerCollege);
university.print();
}
四、安全式与透明式
安全式组合模式:从客户端使用组合模式上看是否安全,如果是安全的,那么就不会发生误操作的可能,能访问的方法都是支持的
透明式组合模式:从客户端使用组合模式上,是否需要区分到底是“树枝对象”还是“树叶对象”。如果是透明的,那就不用区分,对于客户而言,都是Component对象,具体的类型对于客户端而言是透明的
对于组合模式而言,在安全性和透明性上,会更看重透明性,毕竟组合模式的目的是:让客户端不再区分操作的是树枝对象还是树叶对象,而是以一个统一的方式来操作
在使用组合模式的时候,建议多采用透明式的实现方式