GOF对组合模式的定义是:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。来看基本代码
/**
*
* @author ricardo
* @Time 下午10:33:52
* @Function:树中分支结点与叶子节点的抽象父类
*
*/
public abstract class Component {
protected String componentName;
public Component(String componentName) {
this.componentName = componentName;
}
//增加分支/叶子节点的方法
public abstract void Add(Component component);
//移除分支/叶子节点的方法
public abstract void Remove(Component component);
//按照深度显示树形结构的方法
public abstract void Show(int depth);
}
/**
*
* @author ricardo
* @Time 下午10:46:16
* @Function:分支节点类
*
*/
public class Composite extends Component {
private List<Component> childrenList = new ArrayList<Component>();
public Composite(String componentName) {
super(componentName);
}
@Override
public void Add(Component component) {
// TODO Auto-generated method stub
childrenList.add(component);
}
@Override
public void Remove(Component component) {
// TODO Auto-generated method stub
childrenList.remove(component);
}
@Override
public void Show(int depth) {
// TODO Auto-generated method stub
for(int i = 0;i < depth;i++) {
System.out.print("+");
}
System.out.print(componentName + '\n');
for(int i = 0;i < childrenList.size();i++) {
childrenList.get(i).Show(depth+2);
}
}
}
/**
*
* @author ricardo
* @Time 下午10:54:27
* @Function:树叶节点类
*
*/
public class Leaf extends Component {
public Leaf(String componentName) {
super(componentName);
}
@Override
public void Add(Component component) {
System.out.println("叶子节点无法增加子节点");
}
@Override
public void Remove(Component component) {
System.out.println("叶子节点无法移除节点");
}
@Override
public void Show(int depth) {
for(int i=0;i<depth;i++) {
System.out.print('+');
}
System.out.print(componentName + '\n');
}
}
客户端实现
public class Client {
public static void main(String[] args) {
Composite root = new Composite("树根");
root.Add(new Leaf("叶子A"));
root.Add(new Leaf("叶子B"));
Composite composite = new Composite("节点X");
composite.Add(new Leaf("叶子XA"));
composite.Add(new Leaf("叶子XB"));
Composite composite2 = new Composite("节点Y");
composite2.Add(new Leaf("叶子YA"));
composite2.Add(new Leaf("叶子YB"));
composite.Add(composite2);
root.Add(composite);
root.Show(1);
}
}
运行截图
有个很符合组合模式的例子就是大学的组织架构,一般一个大学会有学生管理处和教师管理处,又拆分成多个学院,所以大学的管理结构就是一棵树的样子
/**
*
* @author ricardo
* @Time 下午11:05:04
* @Function:部门类
*
*/
public abstract class Department {
protected String name;
public Department(String name) {
this.name = name;
}
//新增部门
public abstract void Add(Department department);
//移除部门
public abstract void Remove(Department department);
//显示部门结构
public abstract void Show(int depth);
//部门汇报工作
public abstract void ReportWork();
}
/**
*
* @author ricardo
* @Time 下午11:12:06
* @Function:实体部门
*
*/
public class ConcreateDepartment extends Department {
private List<Department> childrenList = new ArrayList<Department>();
public ConcreateDepartment(String name) {
super(name);
}
@Override
public void Add(Department department) {
// TODO Auto-generated method stub
childrenList.add(department);
}
@Override
public void Remove(Department department) {
// TODO Auto-generated method stub
childrenList.remove(department);
}
@Override
public void Show(int depth) {
// TODO Auto-generated method stub
for(int i = 0;i < depth;i++) {
System.out.print("+");
}
System.out.print(name + '\n');
for(int i = 0;i < childrenList.size();i++) {
childrenList.get(i).Show(depth+2);
}
}
@Override
public void ReportWork() {
// TODO Auto-generated method stub
for(int i = 0;i<childrenList.size();i++) {
childrenList.get(i).ReportWork();
}
}
}
/**
*
* @author ricardo
* @Time 下午11:12:18
* @Function:学生管理处
*
*/
public class StudentOffice extends Department {
private List<Department> childrenList = new ArrayList<Department>();
public StudentOffice(String name) {
super(name);
}
@Override
public void Add(Department department) {
}
@Override
public void Remove(Department department) {
}
@Override
public void Show(int depth) {
// TODO Auto-generated method stub
for(int i = 0;i < depth;i++) {
System.out.print("+");
}
System.out.print(name + '\n');
for(int i = 0;i < childrenList.size();i++) {
childrenList.get(i).Show(depth+2);
}
}
@Override
public void ReportWork() {
System.out.println(name + "汇报了学生工作");
}
}
/**
*
* @author ricardo
* @Time 下午11:14:01
* @Function:教师管理处
*
*/
public class TeacherOffice extends Department {
private List<Department> childrenList = new ArrayList<Department>();
public TeacherOffice(String name) {
super(name);
}
@Override
public void Add(Department department) {
}
@Override
public void Remove(Department department) {
}
@Override
public void Show(int depth) {
// TODO Auto-generated method stub
for(int i = 0;i < depth;i++) {
System.out.print("+");
}
System.out.print(name + '\n');
for(int i = 0;i < childrenList.size();i++) {
childrenList.get(i).Show(depth+2);
}
}
@Override
public void ReportWork() {
System.out.println(name + "汇报了教师工作");
}
}
客户端代码实现
public class Client {
public static void main(String[] args) {
ConcreateDepartment root = new ConcreateDepartment("XXX大学");
root.Add(new StudentOffice("XXX大学学生管理处"));
root.Add(new StudentOffice("XXX大学教师管理处"));
ConcreateDepartment dep1 = new ConcreateDepartment("计算机科学学院");
dep1.Add(new StudentOffice("计算机科学学院学生管理处"));
dep1.Add(new StudentOffice("计算机科学学院教师管理处"));
ConcreateDepartment dep2 = new ConcreateDepartment("外语学院");
dep2.Add(new StudentOffice("外语学院学生管理处"));
dep2.Add(new StudentOffice("外语学院教师管理处"));
ConcreateDepartment dep3 = new ConcreateDepartment("生命科学学院");
dep3.Add(new StudentOffice("生命科学学院学生管理处"));
dep3.Add(new StudentOffice("生命科学学院教师管理处"));
ConcreateDepartment dep4 = new ConcreateDepartment("农学院");
dep4.Add(new StudentOffice("农学院学生管理处"));
dep4.Add(new StudentOffice("农学院教师管理处"));
root.Add(dep1);
root.Add(dep2);
root.Add(dep3);
root.Add(dep4);
System.out.println("XXX大学的组织结构图");
root.Show(1);
System.out.println("XXX大学招考计算机科学学院工作汇报会议");
dep1.ReportWork();
System.out.println("XXX大学召开全校工作汇报会议");
root.ReportWork();
}
}
运行截图
对于客户来说,管理处是基本对象,而各个学院以及整个大学都是树形组合对象层次结构,基本的对象都能够组合成更加复杂的组合对象,复杂的组合对象同样可以继续集合,当需要开会时,只需要通知到根节点就好,而不需要亲自通知每一个部门。
组合模式还一个优点就是增加新类型的组件非常简单,这是因为新定义的分之内和叶节点类可以自动适应已有的结构和代码,而不需要修改现有代码。
适合于丹开发的代码需要表示部分与整体的结构时,或者用户希望忽略组合对象和单个对象之间的不同时。
以上内容,整理自刘径舟,张玉华编著的《设计模式其实很简单》读书笔记,欢迎转载