设计模式之组合模式
组合模式的基本介绍:
又叫部分整体模式。创建了对象组的树形结构,将对象组合成树形结构以表示"整体-部分"的层次关系。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。组合模式使得用户对单个对象和组合对象的访问具有一致性。即:组合能让客户以一致的方式处理个别对象以及组合对象。
组合模式主要解决的问题:当我们要处理的对象可以生成一颗树形结构,而我们需要对树上的节点或者叶子进行操作时,它可以提供一致的方式,不用考虑时节点还是叶子。
有个一学校院系的展示,需求是这样,一个学校有多个学院,一个学院有多个系,如图:
现在要求编写程序展示学校院系的结构。能够实现管理操作,对院、对系的添加,删除,遍历等。
传统方案,把这三个类之前的关系视为继承关系,如下:
这三个是继承关系。
但是学校和学院,学院和系其实是整体和部分的关系。如果是继承关系,试想一下,这样的方案很难对学院、系进行添加、删除、遍历操作。
解决方案:把学校、院、系都看成是组织结构,他们之间没有继承的关系,而应该是一个树形结构,可以更好的实现管理操作--->我们引入组合模式,因为组合模式就是表示整体-部分的关系,而且是以树形结构来组合对象。
关系类图:
Component: 这是组合中的对象声明接口(可以是抽象类或者接口),实现所有类的共同的接口默认行为。如遍历、添加、删除和获取子节点等。用于访问和管理Component子部件。充当叶子或者节点。
Leaf:在组合中表示的是叶子节点,表示最后的节点,下面不会再有节点。但这个节点定义组合内元素的行为。
Composite:非叶子节点,用于存储子部件,在Component接口中实现子部件的相关操作,就是对接口具体实现。可以操作子节点和叶子,但是不具有叶子的某些行为。
以下用java代码具体实现下以上院校关系。
代码的类图如下:
OrganizationComponent.java
public abstract class OrganizationComponent { private String name; //名字 private String des; //说明 protected void add(OrganizationComponent organizationComponent){ //来一个空实现,因为叶子节点可能不需要这个方法,abstract所有的子类都需要重写其他方法同理。 throw new UnsupportedOperationException(); } protected void remove(OrganizationComponent organizationComponent){ //来一个空实现,因为叶子节点可能不需要这个方法,abstract所有的子类都需要重写其他方法同理。 throw new UnsupportedOperationException(); } public OrganizationComponent(String name, String des) { super(); this.name = name; this.des = des; } //这个方法是都要有的,所以直接做成抽象的。 protected abstract void print(); 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; } }
University.java
import java.util.ArrayList; import java.util.List; //大学类 public class University extends OrganizationComponent { List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>(); public University(String name, String des) { super(name, des); } @Override protected void add(OrganizationComponent organizationComponent) { organizationComponents.add(organizationComponent); } @Override protected void print() { System.out.println("------------" + getName() + "--------------"); for (OrganizationComponent organizationComponent : organizationComponents) { organizationComponent.print(); } } @Override protected void remove(OrganizationComponent organizationComponent) { organizationComponents.remove(organizationComponent); } @Override public String getName() { return super.getName(); } @Override public String getDes() { return super.getDes(); } }
College.java
import java.util.ArrayList; import java.util.List; //院系类 public class College extends OrganizationComponent { List<OrganizationComponent> organizationComponents = new ArrayList<OrganizationComponent>(); public College(String name, String des) { super(name, des); } @Override protected void add(OrganizationComponent organizationComponent) { organizationComponents.add(organizationComponent); } @Override protected void print() { System.out.println("------------" + getName() + "--------------"); for (OrganizationComponent organizationComponent : organizationComponents) { organizationComponent.print(); } } @Override protected void remove(OrganizationComponent organizationComponent) { organizationComponents.remove(organizationComponent); } @Override public String getName() { return super.getName(); } @Override public String getDes() { return super.getDes(); } }
Department.java
//专业类 public class Department extends OrganizationComponent{ public Department(String name, String des) { super(name, des); } //叶子节点的,直接打印出来 @Override protected void print() { System.out.println(getName()); } @Override public String getName() { return super.getName(); } @Override public String getDes() { return super.getDes(); } }
Client.java
public class Client { public static void main(String[] args) { //从大到小,创建对象 //创建学校 OrganizationComponent university = new University("清华大学", "中国顶级大学"); //创建学院 OrganizationComponent componentCollege = new College("计算机学院", "计算机学院"); //创建学院 OrganizationComponent infoEngineerCollege = new College("信息工程学院", "信息工程学院"); //创建学院下面的系 componentCollege.add(new Department("软件工程", "软件工程")); componentCollege.add(new Department("网络工程", "网络工程")); componentCollege.add(new Department("计算机科学与技术", "计算机科学与技术")); //信息工厂学院加上两个专业 infoEngineerCollege.add(new Department("通信工程", "通信工厂")); infoEngineerCollege.add(new Department("信息工程", "信息工程")); university.add(componentCollege); university.add(infoEngineerCollege); university.print(); } }
输出:
------------清华大学-------------- ------------计算机学院-------------- 软件工程 网络工程 计算机科学与技术 ------------信息工程学院-------------- 通信工程 信息工程