学校院系展示
在一个页面展示出学校的院系组成,一个学校有多个学院,一个学院有多个系。
传统方案
根据组织大小分层次。
但该方案不好实现对学校、系的添加、删除、遍历等。
解决方案:把学校、院、系都看作组织结构,他们不是继承关系,而是树形结构,可以更好地实现管理操作。=》组合模式
组合模式
创建了对象组的树形结构,将对象组合成树状结构以表示 整体-部分
的层次关系。
该模式使得用户对单个对象和组合对象的访问具有一致性。使客户能让一致的方式处理个别对象以及组合对象。
组合模式结构
1.
组件 (Component)
接口描述了树中简单项目和复杂项目所共有的操作。
2.叶节点 (Leaf)
是树的基本结构, 它不包含子项目。
一般情况下, 叶节点最终会完成大部分的实际工作, 因为它们无法将工作指派给其他部分。
3.容器 (Container)
——又名 “组合 (Composite)”——是包含叶节点或其他容器等子项目的单位。 容器不知道其子项目所属的具体类, 它只通过通用的组件接口与其子项目交互。
容器接收到请求后会将工作分配给自己的子项目, 处理中间结果, 然后将最终结果返回给客户端。
4.客户端 (Client)
通过组件接口与所有项目交互。 因此, 客户端能以相同方式与树状结构中的简单或复杂项目交互。
组合模式适合应用场景
1.如果你需要实现树状对象结构, 可以使用组合模式。
2.如果你希望客户端代码以相同方式处理简单和复杂元素, 可以使用该模式。
实现方式
1.确保应用的核心模型能够以树状结构表示。 尝试将其分解为简单元素和容器。 记住, 容器必须能够同时包含简单元素和其他容器。
2.声明组件接口及其一系列方法, 这些方法对简单和复杂元素都有意义。
3.创建一个叶节点类表示简单元素。 程序中可以有多个不同的叶节点类。
4.创建一个容器类表示复杂元素。 在该类中, 创建一个数组成员变量来存储对于其子元素的引用。 该数组必须能够同时保存叶节点和容器, 因此请确保将其声明为组合接口类型。
实现组件接口方法时, 记住容器应该将大部分工作交给其子元素来完成。
5.在容器中定义添加和删除子元素的方法。
记住, 这些操作可在组件接口中声明。 这将会违反_接口隔离原则_, 因为叶节点类中的这些方法为空。 但是, 这可以让客户端无差别地访问所有元素, 即使是组成树状结构的元素。
组合模式优缺点
优点:
✔️你可以利用多态和递归机制更方便地使用复杂树结构。
✔️开闭原则。 无需更改现有代码, 你就可以在应用中添加新元素, 使其成为对象树的一部分。
缺点:
❌对于功能差异较大的类, 提供公共接口或许会有困难。 在特定情况下, 你需要过度一般化组件接口, 使其变得令人难以理解。
更改后的项目
代码:
public abstract class OrganizationCompoent {
private String name; //名字
private String des; //说明
public OrganizationCompoent(String name, String des) {
super();
this.name = name;
this.des = des;
}
protected void add(OrganizationCompoent organizationCompoent){
//默认实现
throw new UnsupportedOperationException();
}
protected void remove(OrganizationCompoent organizationCompoent){
//默认实现
throw new UnsupportedOperationException();
}
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;
}
//输出由子类实现
protected abstract void print();
}
//最小单位 系
public class Department extends OrganizationCompoent {
public Department(String name, String des) {
super(name, des);
}
//由于是叶子节点(最小单位),因此不用重写add、remove方法
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
@Override
protected void print() {
System.out.println(getName());
}
}
//学院
public class College extends OrganizationCompoent {
//存放系
List<OrganizationCompoent> list = new ArrayList<>();
public College(String name,String des){
super(name,des);
}
@Override
protected void add(OrganizationCompoent organizationCompoent) {
list.add(organizationCompoent);
}
@Override
protected void remove(OrganizationCompoent organizationCompoent) {
list.remove(organizationCompoent);
}
@Override
protected void print() {
System.out.println("----"+getName()+"----");
for (OrganizationCompoent organizationCompoent : list) {
organizationCompoent.print();
}
}
}
//学校,可以管理下面的院系
public class University extends OrganizationCompoent{
//拥有的学院
List<OrganizationCompoent> list = new ArrayList<>();
public University(String name,String des){
super(name,des);
}
@Override
protected void add(OrganizationCompoent organizationCompoent) {
list.add(organizationCompoent);
}
@Override
protected void remove(OrganizationCompoent organizationCompoent) {
list.remove(organizationCompoent);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
@Override
protected void print() {
System.out.println("---"+getName()+"-----");
//遍历list 学院
for (OrganizationCompoent organizationCompoent : list) {
organizationCompoent.print();
}
}
}
public class Client {
public static void main(String[] args) {
//从大向小创建
OrganizationCompoent university = new University("大学","不错的高校");
OrganizationCompoent computerCollege = new College("计算机学院","修电脑的");
OrganizationCompoent buildedCollege = new College("建筑学院","搬砖的");
computerCollege.add(new Department("软件工程","敲代码"));
computerCollege.add(new Department("网络工程","修网线"));
buildedCollege.add(new Department("土木工程","搬砖"));
university.add(computerCollege);
university.add(buildedCollege);
university.print();
}
}
注意:
简化客户端操作。客户端只需要面对一致的对象而不用考虑整体部分或者叶子结点的问题。
具有较强的扩展性。当我们要更改组合对象时,我们只需要调整内部的层次关系,客户端不用做出任何变动
方便创建复杂的层次结构。
当需要遍历组织机构,或者处理的对象具有树形结构时,便可采用组合模式。
具有较高的抽象性,即当节点间的差异较大时,不合适采用组合模式。