组合模式(Composite Pattern)
来源:互联网 发布:linux ld.so.cache 编辑:程序博客网 时间:2024/06/05 15:54
在项目开发中,有时候我们会遇到将一个对象组合成一个树形结构,来表示“整体-部分”的层次关系,但用户在操作的时候,不需要区分组合对象(树枝节点,包含子节点)或单个对象(叶子节点,不包含子节点),保持一致的操作体验。这时候我们就可以利用组合模式来实现我们的应用。
定义:将对象组合成树形结构以表示“部分-整体”的层次结构, 使得用户对单个对象和组合对象的使用具有一致性。
一、透明实现
1、在组合模式中首先我们要定义一个抽象类,实现树枝节点和叶子节点的公共属性及方法(例如下面代码中的name,position,salary属性及getInfo()方法),并且定义树枝节点,叶子节点的公共抽象方法(例如下例中的:addSubordinete()方法,getAllSubordinates()方法),用来给树枝节点和叶子节点个性实现。
package composite.transparent;import java.util.ArrayList;/** * 抽象类,定义树枝节点和叶子节点的公共属性,方法 * 定义抽象方法,供树枝节点和叶子节点实现 */public abstract class AbstractCorp { private String name;//姓名 private String position;//职位 private String salary;//薪水 //构造方法 public AbstractCorp(String name,String position,String salary){ this.name=name; this.position=position; this.salary=salary; } //抽象方法 增加一个子节点,可能是树枝节点,也可能是树叶节点 public abstract void addSubordinate(AbstractCorp corp); //抽象方法 返回所有的子节点 public abstract ArrayList<AbstractCorp> getAllSubordinates(); //返回信息 protected void getInfo(){ System.out.println("姓名:"+this.name+" 职位:"+this.position+" 薪资:"+this.salary); }}
2、然后我们再定义树枝节点类和叶子节点类继承抽象类,使得树枝节点类和叶子节点类不仅继承抽象类的公共方法和属性,还可以个性化的实现抽象类的抽象方法。
树枝节点类:
package composite.transparent;import java.util.ArrayList;import composite.transparent.AbstractCorp;/** * 树枝节点类 */public class Branch extends AbstractCorp{ private ArrayList<AbstractCorp> subordinateList=new ArrayList<AbstractCorp>();//子节点集合 //构造方法,调用父类的构造方法 public Branch(String name, String position, String salary) { super(name, position, salary); // TODO Auto-generated constructor stub } //实现抽象类的方法 增加一个子节点,可能是树枝节点,也可能是树叶节点 @Override public void addSubordinate(AbstractCorp corp) { // TODO Auto-generated method stub if(this.subordinateList!=null){ this.subordinateList.add(corp); } } //实现抽象类的方法 返回所有的子节点 @Override public ArrayList<AbstractCorp> getAllSubordinates() { // TODO Auto-generated method stub return this.subordinateList; }}
叶子节点类:
package composite.transparent;import java.util.ArrayList;/** * 叶子节点 */public class Leaf extends AbstractCorp{ //构造方法,调用父类的构造方法 public Leaf(String name, String position, String salary) { super(name, position, salary); // TODO Auto-generated constructor stub } /** * 实现抽象类的方法,叶子节点不能再添加子节点,所以 * @Deprecated注解,表示“不建议使用”, * 方法空实现抛出一个UnsupportedOperationException异常 */ @Deprecated @Override public void addSubordinate(AbstractCorp corp){ // TODO Auto-generated method stub throw new UnsupportedOperationException();////空实现,直接抛弃一个"不支持请求"异常 } /** * 实现抽象类的方法,叶子节点不包含任何子节点,所以 * @Deprecated注解,表示“不建议使用”, * 方法空实现抛出一个UnsupportedOperationException异常 */ @Deprecated @Override public ArrayList<AbstractCorp> getAllSubordinates() { // TODO Auto-generated method stub throw new UnsupportedOperationException();////空实现,直接抛弃一个"不支持请求"异常 }}
场景类:
package composite.transparent;import java.util.ArrayList;/** * 场景类 */public class Client { public static void main(String[] args) { // TODO Auto-generated method stub AbstractCorp ceo=new Branch("章建丰","总经理","200w");//总经理 AbstractCorp techDirector=new Branch("周勇军","技术总监","100w");//技术总监 techDirector.addSubordinate(new Leaf("张涛","IOS开发工程师","20k"));//ios开发工程师 techDirector.addSubordinate(new Leaf("魏庭聪","Android开发工程师","20k"));//android开发工程师 techDirector.addSubordinate(new Leaf("冯适","PHP开发工程师","20k"));//php开发工程师 AbstractCorp marketDirector=new Branch("宗玺","市场总监","100w");//市场总监 marketDirector.addSubordinate(new Leaf("张敏","市场营销","30k"));//市场营销 marketDirector.addSubordinate(new Leaf("史帅","市场营销","30k"));//市场营销 marketDirector.addSubordinate(new Leaf("王耀","市场营销","30k"));//市场营销 ceo.addSubordinate(techDirector); ceo.addSubordinate(marketDirector); print(ceo);//遍历所有节点信息 } /** * 打印所有节点信息 * @param root 根节点 */ private static void print(AbstractCorp root){ ArrayList<AbstractCorp> subordinates=root.getAllSubordinates(); for(AbstractCorp subordinate:subordinates){ if(subordinate instanceof Leaf){//叶子节点 subordinate.getInfo();//打印叶子节点的信息 }else{ subordinate.getInfo();//打印树枝节点信息 print((Branch)subordinate);//递归遍历打印 } } }}
所有对象声明为AbstractCorp类型,用户不需要知道自己调用的是组合对象还是单个对象,保持一致性。
如果我们创建一个叶子节点,调用addSubordinate()方法
AbstractCorp leaf=new Leaf("史帅","市场营销","30k");//创建一个叶子节点 leaf.addSubordinate(new Leaf("王耀","市场营销","30k"));//给叶子节点在添加一个子节点
运行,报错:
这是正确的,因为叶子节点不能再添加子节点。但同样这也是不安全的,可能会在运行时出现错误,所以还有另外一种安全的组合模式。
二、安全实现
1、同样首先我们要定义一个抽象类,定义树枝节点和叶子节点的公共属性和方法。
package composite.safe;import java.util.ArrayList;/** * 抽象类,定义树枝节点和叶子节点的公共属性,方法 */public abstract class AbstractCorp { private String name;//姓名 private String position;//职位 private String salary;//薪水 //构造方法 public AbstractCorp(String name,String position,String salary){ this.name=name; this.position=position; this.salary=salary; } //返回信息 protected void getInfo(){ System.out.println("姓名:"+this.name+" 职位:"+this.position+" 薪资:"+this.salary); }}
2、树枝节点
package composite.safe;import java.util.ArrayList;/** * 树枝节点类 */public class Branch extends AbstractCorp{ private ArrayList<AbstractCorp> subordinateList=new ArrayList<AbstractCorp>();//子节点集合 //构造方法,调用父类的构造方法 public Branch(String name, String position, String salary) { super(name, position, salary); // TODO Auto-generated constructor stub } //增加一个子节点,可能是树枝节点,也可能是树叶节点 public void addSubordinate(AbstractCorp corp){ if(this.subordinateList!=null){ this.subordinateList.add(corp); } } //返回所有的子节点 public ArrayList<AbstractCorp> getAllSubordinates(){ return this.subordinateList; }}
继承AbstractCorp类,并且添加了addSubordinate()和getAllSubordinates()方法。
3、叶子节点
package composite.safe;/** * 树叶节点 */public class Leaf extends AbstractCorp{ //构造方法,调用父类的构造方法 public Leaf(String name, String position, String salary) { super(name, position, salary); // TODO Auto-generated constructor stub }}
叶子节点没有子节点,所以没有addSubordinate()和getAllSubordinates()方法。没有添加子节点方法,也就不会出现错误了。
4、场景类
package composite.safe;import java.util.ArrayList;/** * 场景类 */public class Client { public static void main(String[] args) { // TODO Auto-generated method stub Branch ceo=new Branch("章建丰","总经理","200w");//总经理 Branch techDirector=new Branch("周勇军","技术总监","100w");//技术总监 techDirector.addSubordinate(new Leaf("张涛","IOS开发工程师","20k"));//ios开发工程师 techDirector.addSubordinate(new Leaf("魏庭聪","Android开发工程师","20k"));//android开发工程师 techDirector.addSubordinate(new Leaf("冯适","PHP开发工程师","20k"));//php开发工程师 Branch marketDirector=new Branch("宗玺","市场总监","100w");//市场总监 marketDirector.addSubordinate(new Leaf("张敏","市场营销","30k"));//市场营销 marketDirector.addSubordinate(new Leaf("史帅","市场营销","30k"));//市场营销 marketDirector.addSubordinate(new Leaf("王耀","市场营销","30k"));//市场营销 ceo.addSubordinate(techDirector); ceo.addSubordinate(marketDirector); print(ceo);//遍历所有节点信息 } /** * 打印所有节点信息 * @param root 根节点 */ private static void print(Branch root){ ArrayList<AbstractCorp> subordinates=root.getAllSubordinates(); for(AbstractCorp subordinate:subordinates){ if(subordinate instanceof Leaf){//叶子节点 subordinate.getInfo();//打印叶子节点的信息 }else{ subordinate.getInfo();//打印树枝节点信息 print((Branch)subordinate);//递归遍历树枝节点 } } }}
但是,对象无法统一指定为抽象类型,也就是用户需要区分对象是树枝节点还是叶子节点,这与组合模式的定义相违背。
优点:
● 高层模块调用简单
一棵树形机构中的所有节点都是Component, 局部和整体对调用者来说没有任何区别,也就是说, 高层模块不必关心自己处理的是单个对象还是整个组合结构, 简化了高层模块的代码。
● 节点自由增加
使用了组合模式后, 我们可以看看, 如果想增加一个树枝节点、 树叶节点是不是都很容易, 只要找到它的父节点就成, 非常容易扩展, 符合开闭原则, 对以后的维护非常有利。
项目地址
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern )
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式(Composite Pattern)
- 组合模式-Composite Pattern
- Composite Pattern(组合模式)
- jsp页面中frameset的使用方法
- 山大场馆管理系统 开发日志2
- 顺序表
- Roman to Integer 【LeetCode】
- 顺序表
- 组合模式(Composite Pattern)
- 486. Predict the Winner
- LeetCode -- 5. Longest Palindromic Substring
- 算法设计与应用基础
- 织梦搜索结果标题显示不全的解决方法
- 微信中原来有两种纵向滚动条
- 学习模板
- c++输入输出
- 自己写的第一个Gating简单例子