一、组合模式介绍
组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
组合模式使得用户对单个对象和组合对象地访问具有一致性。(即:组合能让客户以一致的方式处理个别对象以及组合对象。)
组合模式成员角色:
Component
:它是组合中对象声明接口,适当情况下,实现所有类共有的接口默认行为,用于访问和管理各个子部件。它可以是抽象类或者接口。Composite
:非叶子节点,用于存储子部件,在Component接口中实现子部件相关操作。Leaf
:在组合中表示叶子节点,叶子节点没有子节点(即:终端节点)。此处我们有一个诉求:设计并展示学校&学院&院系关系。
- 传统实现方式(从组织大小进行分层-如下图)。
- 传统方式缺点:不能很好地实现管理操作(比如添加和删除及遍历等操作)。
- 解决方案:采用组合模式。
二、组合模式使用
2.1 示例关系:
2.2 代码实现:
- 组织部分
/* *
* 组织管理
*/
abstract class OrganizationComponent {
private String name;
public OrganizationComponent(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/* *
* 添加元素方法 - 默认实现。
*/
protected void add(OrganizationComponent component) {
throw new UnsupportedOperationException();
}
/* *
* 删除元素方法 - 默认实现。
*/
protected void remove(OrganizationComponent component) {
throw new UnsupportedOperationException();
}
/* *
* 展示信息的抽象方法-子类都需要去实现。
*/
protected abstract void show();
}
- 学校部分
/* *
* 学校
*/
class University extends OrganizationComponent {
List<OrganizationComponent> components = new ArrayList<>();
public University(String name) {
super(name);
}
@Override
protected void add(OrganizationComponent component) {
components.add(component);
}
@Override
protected void remove(OrganizationComponent component) {
components.remove(component);
}
@Override
public String getName() {
return super.getName();
}
@Override
protected void show() {
System.out.println(" 大学: " + getName());
for (OrganizationComponent component : components) {
component.show();
}
}
}
- 学院部分
/* *
* 学院
*/
class College extends OrganizationComponent {
/* *
* 集合存放Department元素。
*/
List<OrganizationComponent> components = new ArrayList<>();
public College(String name) {
super(name);
}
@Override
protected void add(OrganizationComponent component) {
components.add(component);
}
@Override
protected void remove(OrganizationComponent component) {
components.remove(component);
}
@Override
public String getName() {
return super.getName();
}
@Override
protected void show() {
System.out.println(" 学院: " + getName());
for (OrganizationComponent component : components) {
component.show();
}
}
}
- 院系部分
/* *
* 院系
*/
class Department extends OrganizationComponent {
/* *
* Department为叶子节点,故没有成员集合及add(),remove()方法。
*/
public Department(String name) {
super(name);
}
@Override
public String getName() {
return super.getName();
}
@Override
protected void show() {
System.out.println(" 院系: " + getName());
}
}
- 客户端调用
public class Client {
public static void main(String[] args) {
// 从大到小创建 - 先创建学校
OrganizationComponent qingHuaUniversity = new University("清华大学");
// 再创建学院
OrganizationComponent computerCollege = new College("计算机学院");
OrganizationComponent infoCollege = new College("信息工程学院");
// 不同学院添加不同的院系
computerCollege.add(new Department("软件工程系"));
computerCollege.add(new Department("网络工程系"));
infoCollege.add(new Department("电子信息工程系"));
// 将学院添加至学校
qingHuaUniversity.add(computerCollege);
qingHuaUniversity.add(infoCollege);
qingHuaUniversity.show();
// 大学: 清华大学
// 学院: 计算机学院
// 院系: 软件工程系
// 院系: 网络工程系
// 学院: 信息工程学院
// 院系: 电子信息工程系
System.out.println();
computerCollege.show();
// 学院: 计算机学院
// 院系: 软件工程系
// 院系: 网络工程系
}
}
三、组合模式总结
优点:
- 客户端只需要面对一致的对象而不用考虑整体部分或者节点等问题,简化了客户端操作。
- 需要调整内部层次关系时,客户端不用做任何改动,具有较强的拓展性。
- 方便创建复杂的层次结构。
缺点:
- 有较高的抽象性。
- 如果节点和叶子有很多差异性的话,比如很多方法和属性都不一样,则不适合用组合模式。
应用场景:
- 当需要遍历组织结构,或者处理的对象具有树形结构时,非常适合使用组合模式。
JDK
中的HashMap
源码。
四 、结束语
“-------怕什么真理无穷,进一寸有一寸的欢喜。”
微信公众号搜索:饺子泡牛奶。