被说了很多遍的设计模式---组合模式

来源:互联网 发布:朝鲜核爆东北 知乎 编辑:程序博客网 时间:2024/05/02 06:10

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍组合模式,文章主题结构与上文一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

文件系统的目录结构,公司或政府部门的组织结构等具有树形递归关系的抽象组织结构。

思路分析:

要点一:每一级都可作为一个完整的最小树型结构。

要点二:每一级的外在表现类似,具有屏蔽层次结构的功能。如:文件系统不同级别的目录都具有相同的表现形式。分级行政办公组织结构中的相同部门设置。

要点三:对软件实现而言,需要尽可能的提高代码复用度。

示例工程:


组合模式模板代码【本例我们先展示模板代码,稍后演示一个具体的示例】


创建Component.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;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);}
创建Composite.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;import java.util.ArrayList;import java.util.List;public class Composite extends Component {private List<Component> children = new ArrayList<Component>();public Composite(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void add(Component c) {// TODO Auto-generated method stubchildren.add(c);}@Overridepublic void remove(Component c) {// TODO Auto-generated method stubchildren.remove(c);}@Overridepublic void display(int depth) {// TODO Auto-generated method stubSystem.out.println("-"+name);for(Component c:children){c.display(depth+1);}}}
创建Leaf.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;public class Leaf extends Component{public Leaf(String name) {super(name);}@Overridepublic void add(Component c) {// TODO Auto-generated method stubSystem.out.println("cannot add to leaf");}@Overridepublic void remove(Component c) {System.out.println("cannot remove from a leaf");}@Overridepublic void display(int depth) {// TODO Auto-generated method stubSystem.out.println(new String("----")+"depth:"+depth+"name:"+name);}}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite;public class Window {public static void main(String[] args) {Composite root = new Composite("root");root.add(new Leaf("Leaf A"));root.add(new Leaf("Leaf B"));Composite comp = new Composite("ComposteX");comp.add(new Leaf("Leaf XA"));comp.add(new Leaf("Leaf XB"));root.add(comp);Composite comp2 = new Composite("ComposteXY");comp2.add(new Leaf("Leaf XYA"));comp2.add(new Leaf("Leaf XYB"));comp.add(comp2);root.add(new Leaf("Leaf C"));Leaf l = new Leaf("Leaf D");root.add(l);root.remove(l);root.display(1);}}

【上面的代码直接看的话,可能有难度。先把代码提供给各位看官是希望现将代码运行起来,观察结果。下面我们介绍相关的概念与原理】

模式总结:

组合模式结构图:


组合模式:

将对象组合成属性结构以表示“部分--整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

组成部分:

Component:抽象构件。可以是接口或者抽象类。其中包含leaf与composite公共接口的声明。如,增删改功能。

Leaf:叶子节点。其实就是最后一级节点,其下不能再有任何形式的impl或extend关系。其本身必须实现Component中定义的内容。

Composite:容器组件。是相对于Leaf定义的。其下还能够挂载其他的节点(可以是Leaf或Composite)。其中,可以通过递归实现对子部件的调用。

【以上,可以类比文件系统中的文件夹,文件夹可以包含文件或文件夹,文件本身不能包含其他文件或文件夹】

特别提示:上面的模板代码,在leaf与Composite中都包含了add和remove方法。但事实上,只有Composite的中的方法才是有效的。

实际场景用例:

需求描述:

公司包括:子公司,人力,研发,财务。子公司包括:子公司(可选的),人力,研发,财务。等等。

示例代码:


创建Company.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;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();}
创建ConcreteCompany.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;import java.util.ArrayList;import java.util.List;public class ConcreteCompany extends Company {private List<Company> children = new ArrayList<Company>();public ConcreteCompany(String name) {super(name);// TODO Auto-generated constructor stub}@Overridepublic void add(Company c) {// TODO Auto-generated method stubchildren.add(c);}@Overridepublic void remove(Company c) {// TODO Auto-generated method stubchildren.remove(c);}@Overridepublic void display(int depth) {// TODO Auto-generated method stubSystem.out.println("-"+name);for(Company c:children){c.display(depth);}}@Overridepublic void lineOfDuty() {// TODO Auto-generated method stubfor(Company c:children){c.lineOfDuty();}}}
创建FinanceDepartment.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;public class FinanceDepartment extends Company{public FinanceDepartment(String name) {super(name);}@Overridepublic void add(Company c) {// TODO Auto-generated method stub}@Overridepublic void remove(Company c) {// TODO Auto-generated method stub}@Overridepublic void display(int depth) {// TODO Auto-generated method stubSystem.out.println("----"+name);}@Overridepublic void lineOfDuty() {// TODO Auto-generated method stubSystem.out.println("finance duty:"+name);}}
创建HRDepartment.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;public class HRDepartment extends Company{public HRDepartment(String name) {super(name);}@Overridepublic void add(Company c) {// TODO Auto-generated method stub}@Overridepublic void remove(Company c) {// TODO Auto-generated method stub}@Overridepublic void display(int depth) {// TODO Auto-generated method stubSystem.out.println("----"+name);}@Overridepublic void lineOfDuty() {// TODO Auto-generated method stubSystem.out.println("HR duty:"+name);}}

创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_Composite.one;public class Window {public static void main(String[] args) {;Company root = new ConcreteCompany("总公司");root.add(new HRDepartment("总公司人力资源部"));root.add(new FinanceDepartment("总公司财务部"));ConcreteCompany comp1 = new ConcreteCompany("上海分公司");comp1.add(new HRDepartment("上海分公司人力资源部"));comp1.add(new FinanceDepartment("上海分公司财务部"));root.add(comp1);ConcreteCompany comp2 = new ConcreteCompany("南京分公司");comp2.add(new HRDepartment("南京分公司人力资源部"));comp2.add(new FinanceDepartment("南京分公司财务部"));root.add(comp2);root.display(1);root.lineOfDuty();}}

注:与模板代码对比,这里root对象也可以是抽象类Company。但,具体组织需要特别声明为具体实现。

模式扩展:

在上文中,我们说只有composite中的add和remove是有效的。

事实上,这些方法的设置在组合模式中成为透明组合模式,安全组合模式。即,在透明组合模式中,这些方法不区分leaf与composite。具体应用时可以通过返回值的变化或异常信息返回。而,安全组合模式要求父类不提供该方法的声明,而是由composite进行声明,这样在Window主类中就需要区别声明leaf与composite两个对象。

反思:

应用场景:

  1. 具有整体与部分的树形层次结构关系时,希望通过相同的结构屏蔽层次之间的差异性。
  2. 不同树形层次的功能具有类似性,并且希望达到重用的目的。
  3. 层次关系是不固定的,需要按照需求修改。

优点:

  1. 组合模式能够清楚的定义出复杂的关系。并且向客户端屏蔽了这种复杂与差异性。
  2. 客户端使用树形结构中的任何一个关系,可以通过一个统一的接口。有效减少客户端的依赖程度。
  3. 对树形结构的调整非常方便。而树形结构本身可能是非常复杂的。

缺点:

  1. 对于树形层次的约束不够。如,在组织关系处理中,子公司内不需要设置***部,但由于没有强制的约束条件,客户端可以随意修改。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---组合模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


1 0
原创粉丝点击