组合模式
应用实例要求:
编写程序展示一个学校院系结构:需求是这样,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系
思路分析和图解
代码实现
客户端:
package composite;
public class Client {
public static void main(String[] args){
//从大到小创建对象
//创建学校
OrganizationComponent university=new University("清华大学","最强");
//创建 学院
OrganizationComponent College1=new College("计算机学院","很强");
OrganizationComponent College2=new College("电子学院","也很强");
//将学院加入到学校中
university.add(College1);
university.add(College2);
//创建各个学院下面的专业
College1.add(new Department("软件工程","yyds"));
College1.add(new Department("网络工程","yyds"));
College1.add(new Department("计算机科学与技术","yyds"));
//
College2.add(new Department("信息工程","yyds"));
College2.add(new Department("通信工程","yyds"));
university.print();
}
}
College类:
package composite;
import java.util.ArrayList;
import java.util.List;
public class College extends OrganizationComponent{
public College(String name, String des) {
super(name, des);
}
//College就是Composite,可以管理Department,存放的是Department
List<OrganizationComponent> organzationComponents=new ArrayList<OrganizationComponent>();
//重写add方法
@Override
protected void add(OrganizationComponent organizationComponent){
//在实际业务中,College和University中的add方法不一定完全相同
organzationComponents.add(organizationComponent);
}
//重写remove方法
@Override
protected void remove(OrganizationComponent organizationComponent){
organzationComponents.remove(organizationComponent);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
//输出College中包含的Departments
@Override
protected void print() {
System.out.println("-------------"+getName()+"-------------");
//遍历organzationCompontents
for (OrganizationComponent organzationComponent:organzationComponents
) {
organzationComponent.print();
}
}
}
Department类:
package composite;
public class Department extends OrganizationComponent{
public Department(String name, String des) {
super(name, des);
}
@Override
protected void print() {
System.out.print(getName());
}
@Override
public String getDes() {
return super.getDes();
}
@Override
public String getName() {
return super.getName();
}
//add,和remove方法就不需要写了,叶子节点不需要管理其他单位
}
University类:
package composite;
import java.util.ArrayList;
import java.util.List;
public class University extends OrganizationComponent{
//University就是Composite,可以管理College
List<OrganizationComponent> organzationComponents=new ArrayList<OrganizationComponent>();
//构造器
public University(String name, String des) {
super(name, des);
}
//重写add方法
@Override
protected void add(OrganizationComponent organizationComponent){
organzationComponents.add(organizationComponent);
}
//重写remove方法
@Override
protected void remove(OrganizationComponent organizationComponent){
organzationComponents.remove(organizationComponent);
}
@Override
public String getName() {
return super.getName();
}
@Override
public String getDes() {
return super.getDes();
}
//输出University中包含的College
@Override
protected void print() {
System.out.println("-------------"+getName()+"-------------");
//遍历organzationCompontents
for (OrganizationComponent organzationComponent:organzationComponents
) {
organzationComponent.print();
}
}
}
OrganzationCompontent抽象类(或接口或父类):
package composite;
public abstract class OrganizationComponent{
private String name; //该组织结构名字
private String des; //该组织机构描述
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;
}
//方法print,作为抽象方法(子类都需要实现)
protected abstract void print();
}
组合模式的注意事项和细节
优点
1.简化了客户端操作:客户端只需要面对一致的对象而不用考虑整体部分或叶子节点的问题,他只需要明白谁包含谁就可以
2.具有较强的扩展性:当我们需要更改组合对象时,我们只需要调整内部的层次关系,客户端是不用做出任何改动的
这个关系是我们人为的选择的,只需要我们设计者明白这个关系就可以了,客户端并不关心
3.方便创建出复杂的层次结构,客户端不用例会组合里面的组成细节,容易添加节点或者叶子从而创建出复杂的树形结构
所以我们什么时候需要用到组合模式呢?:就是需求中需要遍历组织机构,或者处理的对象具有树形结构时,非常适合
**注意:**需要有比较高的抽象性,**如果节点和叶子有很多差异性的话,**比如很多方法和属性都不一样,不适合使用组合模式
比如前面所讲到的College和University和Department大致的方法都是比较相似的,大家都有名字,描述,都有共同要打印的方法,所以相似度比较高,适用组合模式
备注:抽象类:父类是抽象类,其中有抽象方法,那么子类继承父类,并把父类中的所有抽象方法都实现(覆盖)了,子类才有创建对象的实例的能力,否则子类也必须是抽象类。抽象类中可以有构造方法,是子类在构造子类对象时需要调用的父类(抽象类)的构造方法。
方法为什么要写成默认实现而不是抽象方法? :譬如OrganizationComponent中的add方法,在leaf中是不需要再去重写这个方法的,而子类只有在调用了父类中全部的抽象方法之后才可以实例化对象,所以是不建议写成抽象方法的。