什么是组合模式
组合模式是将对象组合成树形结构以表示“部分—整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
原理类图
为什么要用组合模式
今年学校的创新创业大赛结果非常好啊,计算机学院有一组学生做出来一份非常好的作品。这个产品可以提供一个非常高效的师生信息流通的渠道。学院打算加以应用并推广。
为了保证这产品确实可用,不会推出后学生没法用,学院不好处理。学院打算先在学院内部使用一下:
计算机学院:
public class ITAcademy {
public void useProduct() {
System.out.println("计算机学院使用产品");
}
}
使用产品:
public class Main {
public static void main(String[] args) {
ITAcademy IT = new ITAcademy();
IT.useProduct();
}
}
非常好,这个产品可以使用。
那么,推广吧,给学校过过眼。
学校综合考虑之后,决定使用并通知各学院和独立学院也可以使用这款产品。
注:独立学院是一个学校,比如浙江大学宁波理工学院
但是,怎么给学校呢?
-
直接把代码复制给学校一份
- 这样确实可以使用,但是学校与学院和独立学院的关系就不那么紧密了
-
让各学院继承计算机学院
- 这样也是一种办法,但是让学校继承计算机学院,似乎有些不妥;同样的,其他学院和计算机学院应该是平级的,直接继承确实不妥
-
把学校作为根,让各学院继承学校
- 这样似乎没什么问题了,各部分之间的关系有了,同时还有了继承关系;
- 但是,独立学院怎么办?独立学院作为一个独立的学校,下面也有很多学院,让那些独立学院的学院也继承这个学校吗?不妥把,那独立学院的计算机学院岂不是和独立学院平级了。
-
应用组合模式,把各个学院组合进学校里面,同时把独立学院也组合进学校里面,独立学院也可以组合其下属的各个学院。
那么,用组合模式实现一下吧:
首先有一个抽象的学校(Component):
public abstract class AbstractUniversity {
protected String name;
public AbstractUniversity(String name) {
this.name = name;
}
public abstract void add(AbstractUniversity abstractUniversity);
public abstract void remove(AbstractUniversity abstractUniversity);
public abstract void useProduct(int depth);
}
学校的具体实现(Composite):
public class University extends AbstractUniversity {
private List<AbstractUniversity> academies = new ArrayList<>();
public University(String name) {
super(name);
}
@Override
public void add(AbstractUniversity abstractUniversity) {
academies.add(abstractUniversity);
}
@Override
public void remove(AbstractUniversity abstractUniversity) {
academies.remove(abstractUniversity);
}
@Override
public void useProduct(int depth) {
System.out.println(name + "使用产品,层级:" + depth);
for (AbstractUniversity abstractUniversity : academies) {
abstractUniversity.useProduct(depth + 1);
}
}
}
学院(Leaf):
public class Academy extends AbstractUniversity {
public Academy(String name) {
super(name);
}
@Override
public void add(AbstractUniversity abstractUniversity) {
System.out.println(name + "没有下属学院,无法添加");
}
@Override
public void remove(AbstractUniversity abstractUniversity) {
System.out.println(name + "没有下属学院,无法删除");
}
@Override
public void useProduct(int depth) {
System.out.println(name + "使用产品,层级:" + depth);
}
}
最后模拟一下:
public class Main {
public static void main(String[] args) {
University university = new University("学校本部");
University college = new University("独立学院");
university.add(new Academy("本部计算机学院"));
university.add(new Academy("本部物理学院"));
university.add(college);
college.add(new Academy("独立学院计算机学院"));
college.add(new Academy("独立学院物理学院"));
university.useProduct(1);
}
}
输出结果:
学校本部使用产品,层级:1
本部计算机学院使用产品,层级:2
本部物理学院使用产品,层级:2
独立学院使用产品,层级:2
独立学院计算机学院使用产品,层级:3
独立学院物理学院使用产品,层级:3
这样,这个产品重要可以在学校里有层级关系得使用了。