一、组合模式的定义
组合模式(Composite Pattern)也叫合成模式,有时又叫做部分-整体模式(Part-Whole),主要是用来描述部分与整体的关系,其定义如下:Compose objects into tree structures to represent part-whole hierarchies.Composite lets clients treat individual objects and compositions of objects uniformly.(将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。)
这个定义谁看完谁迷糊。。什么叫做“对单个对象和组合对象的使用具有一致性”,“一致性”是啥意思?
组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组织成树形结构,在这个树形结构中有两种类型的对象:叶子对象(Leaf)和容器对象(Composite)。叶子对象是组合中的基本单元,它没有子对象。容器对象可以包含叶子对象和其他容器对象,形成一个递归的树形结构。
组合模式定义了一个通用的组件接口,该接口声明了对叶子对象和容器对象进行操作的方法。叶子对象和容器对象都实现了这个接口,但是对于容器对象,它的实现中可能还包含了对子对象的管理操作,比如添加、删除和遍历子对象等。
通过使用组合模式,你可以将单个对象和组合对象都视为一个组件,客户端无需区分处理单个对象还是组合对象,可以一致地对待它们(这就是所谓的一致性)。这样简化了客户端的代码,同时也提供了灵活性,可以动态地增加、删除和修改对象的组合结构。
组合模式的通用类图如下所示:
1、组合模式中的角色
- Component:这是组合模式中的对象声明接口,在适当情况下,实现所有类共有的接口默认行为,用于访问和管理 Component子部件,Component 可以是抽象类或者接口
- Leaf : 在组合中表示叶子节点,叶子节点没有子节点 ,是最末端的存放数据的结构
- Composite:非叶子节点, 用于存储子部件,在 Component 接口中实现子部件的相关操作,比如增加(add),删除 (remove)
2、组合模式解决的问题
组合模式主要用于处理对象的层次结构和组合关系,将对象组织成树形结构,并以一致的方式处理单个对象和对象组合。
也就是说,组合模式解决这样的场景,当我们的要处理的对象可以生成一颗树形结构,而我们要对树上的节点和叶子进行操作时,组合模式能够提供一致的方式,而不用考虑它是节点还是叶子。
二、组合模式案例
案例:在一个页面展示院校-学院-专业。一个学校会有多个学院, 一个学院有会多个专业,它的组织结构图就是一个很标准的树状结构
使用组合模式实现该案例,类图如下
OrganizationComponent
public abstract class OrganizationComponent {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OrganizationComponent(String name) {
this.name = name;
}
public void add(OrganizationComponent component) {
throw new UnsupportedOperationException();
}
public void remove(OrganizationComponent component) {
throw new UnsupportedOperationException();
}
public abstract void show();
}
School
学校类
public class School extends OrganizationComponent {
/**
* 组合的是学院
*/
List<OrganizationComponent> componentList = new ArrayList<>();
public School(String name) {
super(name);
}
@Override
public void add(OrganizationComponent component) {
componentList.add(component);
}
@Override
public void remove(OrganizationComponent component) {
componentList.remove(component);
}
@Override
public String getName() {
return super.getName();
}
@Override
public void show() {
System.out.println("----"+getName()+"----");
for (OrganizationComponent organizationComponent : componentList) {
organizationComponent.show();
}
}
}
College
学院类
public class College extends OrganizationComponent {
/**
* 组合的是专业
*/
List<OrganizationComponent> componentList = new ArrayList<>();
public College(String name) {
super(name);
}
@Override
public void add(OrganizationComponent component) {
componentList.add(component);
}
@Override
public void remove(OrganizationComponent component) {
componentList.remove(component);
}
@Override
public String getName() {
return super.getName();
}
@Override
public void show() {
System.out.println("----"+getName()+"----");
for (OrganizationComponent organizationComponent : componentList) {
organizationComponent.show();
}
}
}
Majar
专业类
public class Majar extends OrganizationComponent {
public Majar(String name) {
super(name);
}
@Override
public String getName() {
return super.getName();
}
@Override
public void show() {
System.out.println(getName());
}
}
启动类
public class Client {
public static void main(String[] args) {
OrganizationComponent school = new School("清华大学");
OrganizationComponent computerCollege = new College("计算机学院");
OrganizationComponent infoCollege = new College("外国语学院");
school.add(computerCollege);
school.add(infoCollege);
computerCollege.add(new Majar("计算机科学与技术专业"));
computerCollege.add(new Majar("软件工程专业"));
infoCollege.add(new Majar("英语专业"));
infoCollege.add(new Majar("日语专业"));
infoCollege.add(new Majar("俄语专业"));
school.show();
}
}
运行结果
----清华大学----
----计算机学院----
计算机科学与技术专业
软件工程专业
----外国语学院----
英语专业
日语专业
俄语专业
三、组合模式优缺点
组合模式优点:
- 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,屏蔽了对象系统的层次差异性,使用一致的行为控制不同层次
- 扩展性非常高,可以很方便地增加 树枝节点 和 叶子节点 对象,并对现有类库无侵入,满足“开闭原则”
组合模式缺点:
要求较高的抽象性,如果叶子和节点有很多差异性的话,例如很多属性和方法都不一样,不适合使用组合模式,而本案例院校展示,他们很多属性和方法都是共同的,类似一个树形结构
四、源码中的组合模式
比如Java AWT 和 Swing GUI 库:Java AWT(Abstract Window Toolkit)和 Swing 是 Java 编程语言中用于创建图形用户界面(GUI)的库。它们使用了组合模式来构建 GUI 组件的层次结构,例如窗口、面板、按钮、文本框等。这些组件可以嵌套在彼此之内,形成一个树形结构,并以一致的方式进行操作和管理。
。。没啥好说的,这个组合模式真是有点奇怪,就太过于简单以至于不知道该说点什么好,我们自己封装的TreeUtil工具类不都用了组合模式
END.
注意:本文归作者所有,未经作者允许,不得转载