设计模式----组合模式
今天来介绍一种新的设计模式:组合模式。
当我们想要实现有层次的结构,比如公司结构,或者学校结构等,它们的层次结构很像数据结构的树,今天介绍的这个设计模式也就是实现这个数据结构的。
模板:
接口:
/** * @author 陈柏宇 * 组合模式,适合有层次的结构使用,典型的树形结构。 */ public abstract class Component { protected String name; public Component(String name){ this.name = name; } //增加子节点 public abstract void add(Component component); //删除子节点 public abstract void remove(Component component); //展示自己和所有子节点 public abstract void show(int depth); }
叶节点:
public class Leaf extends Component{ public Leaf(String name) { super(name); } @Override public void add(Component component) { System.out.println("叶节点无法添加子节点"); } @Override public void remove(Component component) { System.out.println("叶节点没有子节点"); } @Override public void show(int depth) { StringBuffer buffer = new StringBuffer(depth); for (int i=0;i<depth;i++) buffer.append('-'); System.out.println(buffer + name); } }
子树节点:
public class Composite extends Component{ List<Component> list = new ArrayList<>(); public Composite(String name) { super(name); } @Override public void add(Component component) { list.add(component); } @Override public void remove(Component component) { list.remove(component); } @Override public void show(int depth) { StringBuffer buffer = new StringBuffer(depth); for (int i=0;i<depth;i++) buffer.append('-'); System.out.println(buffer + name); for (Component component : list) { component.show(depth + 2); } } }
客户端代码:
public static void main(String[] args) { Component root = new Composite("root"); root.add(new Leaf("Leaf A")); root.add(new Leaf("Leaf B"));
Component comp = new Composite("Composite X"); comp.add(new Leaf("Leaf XA")); comp.add(new Leaf("Leaf XB")); root.add(comp); Component comp2 = new Composite("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.show(1); }
控制台输出:
-root ---Leaf A ---Leaf B ---Composite X -----Leaf XA -----Leaf XB -----Composite XY -------Leaf XYA -------Leaf XYB ---Leaf C
现在我来举一个具体的例子:
我的大学是南京林业大学,大学前两年我是在淮安校区度过的,于是淮安校区就可以看作是南京林业大学的一个子校区,而南京林业大学本身又有很多学院,学院底下也分很多专业,
所以这就是一个很典型的树形结构。
代码:
抽象类,学术机构类:
public abstract class Academy { protected String name; public Academy(String name){ this.name = name; } //增加子校区或者学院 public abstract void add(Academy university); //删除子校区或者学院 public abstract void remove(Academy university); //展示自己和子节点 public abstract void display(int depth); //履行职责 public abstract void duty(); }
大学类,实现学术机构接口
/** * @author 陈柏宇 * 大学类,子节点是分校区或者学院 */ public class University extends Academy { List<Academy> list = new ArrayList<>(); public University(String name) { super(name); } @Override public void add(Academy academy) { list.add(academy); } @Override public void remove(Academy academy) { list.remove(academy); } @Override public void display(int depth) { StringBuffer buffer = new StringBuffer(depth); for (int i=0;i<depth;i++) buffer.append('-'); System.out.println(buffer + name); for (Academy academy : list) { academy.display(depth + 2); } } @Override public void duty() { System.out.println(name + "大学,负责管理学院。"); for (Academy academy : list) { academy.duty(); } } }
学院类:
/** * @author 陈柏宇 * 学院类,子类是专业类 */ public class College extends Academy{ List<Academy> majors = new ArrayList<>(); public College(String name) { super(name); } @Override public void add(Academy academy) { majors.add(academy); } @Override public void remove(Academy academy) { majors.remove(academy); } @Override public void display(int depth) { StringBuffer buffer = new StringBuffer(depth); for (int i=0;i<depth;i++) buffer.append('-'); System.out.println(buffer + name ); for (Academy major : majors) { major.display(depth + 2); } } @Override public void duty() { System.out.println(name + "学院,负责管理各专业。"); for (Academy major : majors) { major.duty(); } } }
专业类:叶节点
/** * @author 陈柏宇 * 专业类 */ public class Major extends Academy{ public Major(String name) { super(name); } @Override public void add(Academy university) { System.out.println("专业无法再分类了!"); } @Override public void remove(Academy university) { System.out.println("专业无法删除分类了!"); } @Override public void display(int depth) { StringBuffer buffer = new StringBuffer(depth); for (int i=0;i<depth;i++) buffer.append('-'); System.out.println(buffer + name); } @Override public void duty() { System.out.println(name + "专业,负责专业人才培养。"); } }
客户端代码:
public static void main(String[] args) { Academy NJFU = new University("南京林业大学本部"); Academy NjfuHuai = new University("南京林业大学淮安校区"); NJFU.add(NjfuHuai); Academy ComputerScience = new College("本部计算机学院"); ComputerScience.add(new Major("本部软件工程专业")); ComputerScience.add(new Major("本部计算机科学专业")); Academy Mechanics = new College("本部机械电子工程学院"); Mechanics.add(new Major("本部机电专业")); Mechanics.add(new Major("本部机械设计制造专业")); NJFU.add(ComputerScience); NJFU.add(Mechanics); Academy ComputerScienceHuai = new College("淮安校区计算机学院"); ComputerScienceHuai.add(new Major("淮安校区软件工程专业")); ComputerScienceHuai.add(new Major("淮安校区计算机科学专业")); Academy MechanicsHuai = new College("淮安校区机械电子工程学院"); MechanicsHuai.add(new Major("淮安校区机电专业")); MechanicsHuai.add(new Major("淮安校区机械设计制造专业")); NjfuHuai.add(ComputerScienceHuai); NjfuHuai.add(MechanicsHuai); NJFU.display(1); System.out.println("***********************职责********************"); NJFU.duty(); }
控制台输出:
-南京林业大学本部 ---南京林业大学淮安校区 -----淮安校区计算机学院 -------淮安校区软件工程专业 -------淮安校区计算机科学专业 -----淮安校区机械电子工程学院 -------淮安校区机电专业 -------淮安校区机械设计制造专业 ---本部计算机学院 -----本部软件工程专业 -----本部计算机科学专业 ---本部机械电子工程学院 -----本部机电专业 -----本部机械设计制造专业 ***********************职责******************** 南京林业大学本部大学,负责管理学院。 南京林业大学淮安校区大学,负责管理学院。 淮安校区计算机学院学院,负责管理各专业。 淮安校区软件工程专业专业,负责专业人才培养。 淮安校区计算机科学专业专业,负责专业人才培养。 淮安校区机械电子工程学院学院,负责管理各专业。 淮安校区机电专业专业,负责专业人才培养。 淮安校区机械设计制造专业专业,负责专业人才培养。 本部计算机学院学院,负责管理各专业。 本部软件工程专业专业,负责专业人才培养。 本部计算机科学专业专业,负责专业人才培养。 本部机械电子工程学院学院,负责管理各专业。 本部机电专业专业,负责专业人才培养。 本部机械设计制造专业专业,负责专业人才培养。
其中组合模式也分为透明模式和安全模式。
透明模式是指无论你是叶节点还是子树节点你都可以执行add和remove操作。
而安全模式则在接口中不写add()和remove()方法,只在子树结构中写。
两者的使用视情况而定。