第十章:组合模式
一、问题引入
现在要求打印一学校学生会信息,打印的信息包括校学生会、学生会各部门以及各部门的组成人员。
不难发现,打印的三个部分属于整体和部分的关系,例如学生会各部门组成了校学生会。所以针对这个问题,我们使用组合模式。
二、组合模式
组合模式一般类图:
- Component 是所有组成部分的抽象类,里面定义了一些操作子节点的方法
- Leaf 即叶子节点,表示内部不再有组成部分的节点,例如学生会成员
- Composite 即非叶子节点,其内部仍有其他的组成部分
三、解决案例
Component 类
public abstract class Component {
abstract void print();
boolean add(Component component) {
return false;
}
boolean remove(Component component) {
return false;
}
Component getChild(int index) {
return null;
}
}
Member 类
public class Member extends Component {
private String info;
public Member(String info) {
this.info = info;
}
@Override
void print() {
System.out.println(info);
}
}
StudentUnion 类
public class StudentUnion extends Component {
private List<Component> children;
private String info;
public StudentUnion(String info) {
this.children = new ArrayList<>();
this.info = info;
}
@Override
void print() {
System.out.println(info);
for (int i = 0; i < children.size(); i++) {
if (i == 0) {
System.out.println("=========================");
children.get(i).print();
} else {
children.get(i).print();
}
}
System.out.println();
}
@Override
boolean add(Component component) {
return children.add(component);
}
@Override
boolean remove(Component component) {
return children.remove(component);
}
@Override
Component getChild(int index) {
return children.get(index);
}
}
Department 类
public class Department extends Component {
private List<Component> children;
private String info;
public Department(String info) {
this.children = new ArrayList<>();
this.info = info;
}
@Override
void print() {
System.out.println(info);
for (int i = 0; i < children.size(); i++) {
if (i == 0) {
System.out.println("-------------------------");
children.get(i).print();
} else {
children.get(i).print();
}
}
System.out.println();
}
@Override
boolean add(Component component) {
return children.add(component);
}
@Override
boolean remove(Component component) {
return children.remove(component);
}
@Override
Component getChild(int index) {
return children.get(index);
}
}
测试类
public class ComponentTest {
public static void main(String[] args) {
Member zhangsan = new Member("张三");
Member wangwu = new Member("王五");
Member xiaohong = new Member("小红");
Member xiaolan = new Member("小蓝");
Department advocate = new Department("宣传部");
advocate.add(xiaohong);
advocate.add(xiaolan);
Department liaison = new Department("外联部");
liaison.add(zhangsan);
liaison.add(wangwu);
StudentUnion studentUnion = new StudentUnion("校学生会");
studentUnion.add(advocate);
studentUnion.add(liaison);
studentUnion.print();
}
}
/*************** output ***************
校学生会
=========================
宣传部
-------------------------
小红
小蓝
外联部
-------------------------
张三
王五
*************** output ***************/
四、模式总结
组合模式(Composite Pattern)也称为 整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性。
优点 | 缺点 |
---|---|
组合模式屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),将客户代码与复杂的容器对象解耦,使得客户端可以忽略层次间的差异,使用一致的行为控制不同层次。 | 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系; |
在组合模式可以很方便地增加 树枝节点 和 叶子节点 对象,并对现有类库无侵入,符合 开闭原则; | 组合模式在具体实现上违背了设计模式 接口隔离原则 或 依赖倒置原则; |