组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式抽象代码:
public abstract class Component { protected String name; public Component(String name){ this.name = name; } public abstract void add(Component c); public abstract void remove(Component c); public abstract void display(int depth); }
public class Composite extends Component{ private List<Component> children = new ArrayList<Component>(); public Composite(String name){ super(name); } @Override public void add(Component c) { // TODO Auto-generated method stub children.add(c); } @Override public void remove(Component c) { // TODO Auto-generated method stub children.remove(c); } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(getStr(depth) + name); for(Component component : children){ component.display(depth + 2); } } public String getStr(int depth){ StringBuilder sb = new StringBuilder(); for(int i =0; i < depth; i++){ sb.append('-'); } return sb.toString(); } }
public class Leaf extends Component{ public Leaf(String name){ super(name); } @Override public void add(Component c) { // TODO Auto-generated method stub System.out.println("cannot add to a leaf"); } @Override public void remove(Component c) { // TODO Auto-generated method stub System.out.println("cannot remove from a leaf"); } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(getStr(depth) + name); } public String getStr(int depth){ StringBuilder sb = new StringBuilder(); for(int i =0; i < depth; i++){ sb.append('-'); } return sb.toString(); } }
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Composite root = new Composite("root"); root.add(new Leaf("Leaf A")); root.add(new Leaf("Leaf B")); Composite comp = new Composite("X"); comp.add(new Leaf("Leaf XA")); comp.add(new Leaf("Leaf XB")); root.add(comp); Composite comp2 = new Composite("XY"); comp2.add(new Leaf("Leaf XYA")); comp2.add(new Leaf("Leaf XYB")); comp.add(comp2); root.add(new Leaf("Leaf C")); Leaf leaf = new Leaf("Leaf D"); root.add(leaf); root.remove(leaf); root.display(1); } }
何时使用组合模式?
当发现需求中体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一地使用组合结构中的所有对象时,就应该考虑使用组合模式了。比如分公司或办事处与总公司的关系,就是部分与整体的关系。我们希望公司的组织结构,比如人力资源部,财务部的管理功能可以复用于分公司,这其实就是部分与整体可以被一致对待的问题。我们来代码实现一下。
公司管理系统代码结构图:
public abstract class Company { protected String name; public Company(String name){ this.name = name; } public abstract void add(Company c); public abstract void remove(Company c); public abstract void display(int depth); public abstract void lineOfDuty(); }
public class ConcreteCompany extends Company{ private List<Company> children = new ArrayList<Company>(); public ConcreteCompany(String name){ super(name); } @Override public void add(Company c) { // TODO Auto-generated method stub children.add(c); } @Override public void remove(Company c) { // TODO Auto-generated method stub children.remove(c); } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(getStr(depth) + name); for(Company company : children){ company.display(depth + 2); } } public String getStr(int depth){ StringBuilder sb = new StringBuilder(); for(int i =0; i < depth; i++){ sb.append('-'); } return sb.toString(); } @Override public void lineOfDuty() { // TODO Auto-generated method stub for(Company company : children){ company.lineOfDuty(); } } }
public class FinanceDepartment extends Company{ public FinanceDepartment(String name){ super(name); } @Override public void add(Company c) { } @Override public void remove(Company c) { } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(getStr(depth) + name); } public String getStr(int depth){ StringBuilder sb = new StringBuilder(); for(int i =0; i < depth; i++){ sb.append('-'); } return sb.toString(); } @Override public void lineOfDuty() { System.out.println(name + " 公司财务收支管理"); } }
public class HRDepartment extends Company{ public HRDepartment(String name){ super(name); } @Override public void add(Company c) { } @Override public void remove(Company c) { } @Override public void display(int depth) { // TODO Auto-generated method stub System.out.println(getStr(depth) + name); } public String getStr(int depth){ StringBuilder sb = new StringBuilder(); for(int i =0; i < depth; i++){ sb.append('-'); } return sb.toString(); } @Override public void lineOfDuty() { System.out.println(name + " 员工招聘培训管理"); } }
public class Test1 { public static void main(String[] args){ ConcreteCompany root = new ConcreteCompany("北京总公司"); root.add(new HRDepartment("总公司人力资源部")); root.add(new FinanceDepartment("总公司财务部")); ConcreteCompany comp = new ConcreteCompany("上海华东分公司"); comp.add(new HRDepartment("华东分公司人力资源部")); comp.add(new FinanceDepartment("华东分公司财务部")); root.add(comp); ConcreteCompany comp2 = new ConcreteCompany("南京办事处"); comp2.add(new HRDepartment("南京办事处人力资源部")); comp2.add(new FinanceDepartment("南京办事处财务部")); comp.add(comp2); ConcreteCompany comp3 = new ConcreteCompany("杭州办事处"); comp3.add(new HRDepartment("杭州办事处人力资源部")); comp3.add(new FinanceDepartment("杭州办事处财务部")); comp.add(comp3); root.display(1); System.out.println("职责-----------"); root.lineOfDuty(); } }
组合模式的好处:
用户不用关心到底是处理一个叶节点还是处理一个组合组件,也就用不着为定义组合而写一些选择判断语句了。简单点说,就是组合模式让客户可以一致地使用组合结构和单个对象。