设计模式之禅之设计模式-组合模式

  1. 云栖社区>
  2. 博客>
  3. 正文

设计模式之禅之设计模式-组合模式

无信不立 2016-01-22 11:12:00 浏览367
展开阅读全文

一:组合模式的定义
        --->组合模式(Composite Pattern)也叫合成模式,有时又叫做部分-整体模式(Part-Whole),主要是用来描述部分与整体的关系
        --->将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。


二:组合模式的角色
        ● Component抽象构件角色
                定义参加组合对象的共有方法和属性,可以定义一些默认的行为或属性
        ● Leaf叶子构件
                叶子对象,其下再也没有其他的分支,也就是遍历的最小单位。
        ● Composite树枝构件
                树枝对象,它的作用是组合树枝节点和叶子节点形成一个树形结构。

三:组合模式的应用

组合模式的优点:
        ● 高层模块调用简单
                一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,也就是说,高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。
        ● 节点自由增加
                使用了组合模式后,我们可以看看,如果想增加一个树枝节点、树叶节点是不是都很容易,只要找到它的父节点就成,非常容易扩展,符合开闭原则,对以后的维护非常有利。

组合模式的缺点:
        组合模式有一个非常明显的缺点,看到我们在场景类中的定义,提到树叶和树枝使用时的定义了吗?直接使用了实现类!这在面向接口编程上是很不恰当的,与依赖倒置原则冲突,读者在使用的时候要考虑清楚,它限制了你接口的影响范围。

四:组合模式的应用场景
● 维护和展示部分-整体关系的场景,如树形菜单、文件和文件夹管理。
● 从一个整体中能够独立出部分模块或功能的场景。
● 只要是树形结构,就要考虑使用组合模式,这个一定要记住,只要是要体现局部和整体的关系的时候,而且这种关系还可能比较深,考虑一下组合模式吧。

五:组合模式的最佳实践
        组合模式有两种不同的实现:透明模式和安全模式
                ● 透明模式:透明模式是把用来组合使用的方法放到抽象类中,比如add()、remove()以及getChildren等方法(顺便说一下,getChildren一般返回的结果为Iterable的实现类,很多,大家可以看JDK的帮助),不管叶子对象还是树枝对象都有相同的结构
                ● 安全模式:它是把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全,我们的例子使用了安全模式。

        组合模式的案例:
                -->大家常用的XML结构也是一个树形结构
                -->我们自身的亲戚关系也是一种树形结构
                -->部门的职位等级,页面权限菜单显示搜是树形结构


六:组合模式的例子
【1】公共的抽象类

 1 package com.yeepay.sxf.template16;
 2 /**
 3  * 组合模式的抽象类
 4  * 
 5  *抽象模型中角色的公共部分
 6  *比如:共有的属性,共有的行为方法
 7  * @author sxf
 8  *
 9  */
10 public abstract class ComponentCorp {
11     //公司的每个人都有名字
12     private String name="";
13     //公司的每个人都有职位
14     private String position="";
15     //公司的每个人都有薪水
16     private int salary=0;
17     
18     //抽象类的构造函数
19     public ComponentCorp(String name,String postion,Integer salary){
20         this.name=name;
21         this.position=postion;
22         this.salary=salary;
23     }
24     
25     //获取个人信息
26     public String getInfo(){
27         StringBuffer buffer=new StringBuffer();
28         buffer.append("姓名:"+this.name+"\t");
29         buffer.append("职位:"+this.position+"\t");
30         buffer.append("薪水:"+this.salary+"\t");
31         return buffer.toString();
32     }
33     
34 }
View Code

【2】树叶节点

 1 package com.yeepay.sxf.template16;
 2 /**
 3  * 组合模式中的,部件
 4  * 树叶节点。仅含有公共部分的属性和方法
 5  * @author sxf
 6  *
 7  */
 8 public class Leaf extends ComponentCorp{
 9     
10     //构造函数
11     public Leaf(String name, String postion, Integer salary) {
12         super(name, postion, salary);
13     }
14     
15 }
View Code

【3】树枝节点

 1 package com.yeepay.sxf.template16;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 /**
 7  * 组合模式的整体部分
 8  * 
 9  * 树枝节点
10  * 除去公共部分,有自己特色的部分
11  * @author sxf
12  *
13  */
14 public class Branch extends ComponentCorp {
15     //该节点是可以拥有下属节点的特权(除共有属性行为方法之外,特有的行为)
16     private List<ComponentCorp> subordinateList=new ArrayList<ComponentCorp>();
17     //构造函数
18     public Branch(String name, String postion, Integer salary) {
19         super(name, postion, salary);
20     }
21     //添加下属节点,(除共有属性行为方法之外,特有的行为)
22     public void addBordinate(ComponentCorp componentCorp){
23         this.subordinateList.add(componentCorp);
24     }
25     //获取自己的下属
26     public List<ComponentCorp> getBordinate(){
27         return this.subordinateList;
28     }
29     
30 }
View Code

【4】测试类

 1 package com.yeepay.sxf.template16;
 2 /***
 3  * 客户端测试
 4  */
 5 import java.util.List;
 6 
 7 /**
 8  * 客户端测试
 9  * @author sxf
10  *
11  */
12 public class ClientTest {
13     public static void main(String[] args) {
14         //生成小兵
15         Leaf bin1=new Leaf("兵1", "技术员", 1000);
16         Leaf bin2=new Leaf("兵2", "技术员", 1000);
17         Leaf bin3=new Leaf("兵3", "销售员", 500);
18         Leaf bin4=new Leaf("兵4", "销售员", 500);
19         //生成部分领导
20         Branch order1=new Branch("领导1", "技术经理", 10000);
21         Branch order2=new Branch("领导2", "销售经理", 8000);
22         //生成老板
23         Branch leard=new Branch("老板", "总经理", 200000);
24         
25         //进行组合
26         order1.addBordinate(bin1);
27         order1.addBordinate(bin2);
28         order2.addBordinate(bin3);
29         order2.addBordinate(bin4);
30         leard.addBordinate(order1);
31         leard.addBordinate(order2);
32         
33         //进行遍历
34         List<ComponentCorp> list=leard.getBordinate();
35         for(ComponentCorp c:list){
36             
37             if(c instanceof Leaf){
38                 //是兵
39                 System.out.println("ClientTest.main(兵)"+c.getInfo());
40             }else if(c instanceof Branch){
41                 //是领导
42                 System.out.println("ClientTest.main(领导)"+c.getInfo());
43             }
44         }
45     }
46 }
View Code

 

网友评论

登录后评论
0/500
评论
无信不立
+ 关注