前言:
组合模式亦称: 对象树、Object Tree、Composite,是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。组合模式解决这样的问题,当我们的要处理的对象可以生成一颗树形结构,而 我们要对树上的节点和叶子进行操作时,它能够提供一致的方式,而不用考虑 它是节点还是叶子。
--GoF 的《设计模式》定义:将一组对象组织(Compose)成树形结构,以表示一种“部分 - 整体”的层次结构。组合让客户端可以统一单个对象和组合对象的处理逻辑。
目录
一、结构
二、代码实现
统计大学、各学院、各系的学生
/**
* @Description: 组织抽象类
*
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public abstract class OrganizationComponent {
private String name; // 名字
private String des; // 说明
private int num; // 学生人数
protected void add(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationComponent organizationComponent) {
//默认实现
throw new UnsupportedOperationException();
}
//构造器
public OrganizationComponent(String name, String des) {
super();
this.name = name;
this.des = des;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDes() {
return des;
}
public void setDes(String des) {
this.des = des;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
// 方法print, 做成抽象的, 子类都需要实现
protected abstract void print();
}
/**
* @Description: 学院
*
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public class College extends OrganizationComponent{
// List 中 存放的Department
List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
// 构造器
public College(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
// 将来实际业务中,Colleage 的 add 和 University add 不一定完全一样
organizationComponents.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
@Override
public int getNum() {
// TODO Auto-generated method stub
int num = 0;
for (OrganizationComponent organizationComponent : organizationComponents) {
num += organizationComponent.getNum();
}
return num;
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println();
System.out.println("--------------" + getName() + "--------------人数:" + getNum());
System.out.println();
//遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
/**
* @Description: 系
*
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public class Department extends OrganizationComponent{
List<OrganizationComponent> organizationComponentList = new ArrayList<>();
public Department(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponentList.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponentList.remove(organizationComponent);
}
//add , remove 就不用写了,因为他是叶子节点
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
@Override
public int getNum() {
// TODO Auto-generated method stub
return organizationComponentList.size();
}
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println("--------------" + getName() + "--------------人数:" + getNum());
for (OrganizationComponent organizationComponent : organizationComponentList) {
organizationComponent.print();
}
}
}
/**
* @Description: 学生
*
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public class Student extends OrganizationComponent{
//没有集合
public Student(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
//add , remove 就不用写了,因为他是叶子节点
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
@Override
public int getNum() {
// TODO Auto-generated method stub
return super.getNum();
}
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println(getName());
}
}
/**
* @Description: 大学(Composite)
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public class University extends OrganizationComponent{
List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>();
// 构造器
public University(String name, String des) {
super(name, des);
// TODO Auto-generated constructor stub
}
// 重写add
@Override
protected void add(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.add(organizationComponent);
}
// 重写remove
@Override
protected void remove(OrganizationComponent organizationComponent) {
// TODO Auto-generated method stub
organizationComponents.remove(organizationComponent);
}
@Override
public String getName() {
// TODO Auto-generated method stub
return super.getName();
}
@Override
public String getDes() {
// TODO Auto-generated method stub
return super.getDes();
}
@Override
public int getNum() {
// TODO Auto-generated method stub
int num = 0;
for (OrganizationComponent organizationComponent : organizationComponents) {
num += organizationComponent.getNum();
}
return num;
}
// print方法,就是输出University 包含的学院
@Override
protected void print() {
// TODO Auto-generated method stub
System.out.println("--------------" + getName() + "--------------人数:" + getNum());
//遍历 organizationComponents
for (OrganizationComponent organizationComponent : organizationComponents) {
organizationComponent.print();
}
}
}
/**
* @Description: TODO
* @Author HJW
* @Date 2021/4/22
* @Version V1.0
**/
public class Client {
public static void main(String[] args) {
// TODO Auto-generated method stub
//从大到小创建对象 学校
OrganizationComponent university = new University("清华大学", " 中国顶级大学 ");
//创建 学院
OrganizationComponent computerCollege = new College("计算机学院", " 计算机学院 ");
OrganizationComponent infoEngineercollege = new College("信息工程学院", " 信息工程学院 ");
// 创建系
Department soft = new Department("软件工程", " 软件工程不错 ");
Department network = new Department("网络工程", " 网络工程不错 ");
Department computer = new Department("计算机科学与技术", " 计算机科学与技术是老牌的专业 ");
Department communication = new Department("通信工程", " 通信工程不好学 ");
Department information = new Department("信息工程", " 信息工程好学 ");
soft.add(new Student("张三", "三好学生"));
soft.add(new Student("李四", "三好学生"));
network.add(new Student("王五", "三好学生"));
network.add(new Student("赵六", "三好学生"));
network.add(new Student("田七", "三好学生"));
computer.add(new Student("黑八", "三好学生"));
communication.add(new Student("冯九", "三好学生"));
communication.add(new Student("黄二", "三好学生"));
information.add(new Student("范一", "三好学生"));
information.add(new Student("袁零", "三好学生"));
//创建各个学院下面的系(专业)
computerCollege.add(soft);
computerCollege.add(network);
computerCollege.add(computer);
infoEngineercollege.add(communication);
infoEngineercollege.add(information);
//将学院加入到 学校
university.add(computerCollege);
university.add(infoEngineercollege);
university.print();
// infoEngineercollege.print();
}
}
三、组合模式在HashMap中的应用
public class HashMapComp {
public static void main(String[] args) {
// TODO Auto-generated method stub
Map<Integer,String> hashMap=new HashMap<Integer,String>();
hashMap.put(0, "冠军");//直接存放叶子节点
Map<Integer,String> map=new HashMap<Integer,String>();
map.put(1, "亚军");
map.put(2, "季军");
hashMap.putAll(map);
System.out.println(hashMap);
}
}
public interface Map<K,V> {
//add, remover..
}
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable,Serializable { }
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}
四、组合模式适合应用场景
- 如果需要实现树状对象结构, 可以使用组合模式。
组合模式提供了两种共享公共接口的基本元素类型: 简单叶节点和复杂容器。 容器中可以包含叶节点和其他容器。 这使得你可以构建树状嵌套递归对象结构。
- 如果希望客户端代码以相同方式处理简单和复杂元素, 可以使用该模式。
组合模式中定义的所有元素共用同一个接口。 在这一接口的帮助下, 客户端不必在意其所使用的对象的具体类。
五、组合模式优缺点
- 可以利用多态和递归机制更方便地使用复杂树结构。
- 开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
- XXX对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 需要过度一般化组件接口, 使其变得令人难以理解。
六、与其他模式的关系
-
桥接模式、 状态模式和策略模式 (在某种程度上包括适配器模式) 模式的接口非常相似。 实际上, 它们都基于组合模式——即将工作委派给其他对象, 不过也各自解决了不同的问题。 模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。
-
责任链模式通常和组合模式结合使用。 在这种情况下, 叶组件接收到请求后, 可以将请求沿包含全体父组件的链一直传递至对象树的底部。
-
组合和装饰模式的结构图很相似, 因为两者都依赖递归组合来组织无限数量的对象。
装饰类似于组合, 但其只有一个子组件。 此外还有一个明显不同: 装饰为被封装对象添加了额外的职责, 组合仅对其子节点的结果进行了 “求和”。
但是, 模式也可以相互合作: 你可以使用装饰来扩展组合树中特定对象的行为。