第10章 组合模式【Composite Pattern】

组合模式的基本介绍

  1. 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。
  2. 这种类型的设计模式属于结构型模式。
  3. 组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象

组合模式的通用类图

在这里插入图片描述
我们先来说说组合模式的几个角色:

  1. 抽象构件角色(Component):定义参加组合的对象的共有方法和属性,可以定义一些默认的行为或属性;
  2. 叶子构件(Leaf):叶子对象,其下再也没有其他的分支。
  3. 树枝构件(Composite):树枝对象,它的作用是组合树枝节点和叶子节点;
    组合模式有两种模式,透明模式和安全模式,这两个模式有什么区别呢?先看类图:

安全模式类图
在这里插入图片描述
透明模式类图
在这里插入图片描述
从类图上大家应该能看清楚了,这两种模式各有优缺点,透明模式是把用来组合使用的方法放到抽象类中,比如 add(),remove()以及 getChildren 等方法(顺便说一下,getChildren 一般返回的结果为 Iterable的实现类,很多,大家可以看 JDK 的帮助),不管叶子对象还是树枝对象都有相同的结构,通过判断是getChildren 的返回值确认是叶子节点还是树枝节点,如果处理不当,这个会在运行期出现问题的,不是很建议的方式;安全模式就不同了,它是把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全,但是客户段无法依赖抽象(Component),违背了依赖倒置原则。

组合模式案例

我们接下来使用安全组合模式来完成一个示例,透明模式大家自行实验

我们有一个公司人事管理的的树状结构,如下图,我们用安全模式将这个梳树状结构实现出来
在这里插入图片描述

直接看代码:

/**
 * 定义一个公司的人员的抽象类
 */
public abstract class Corp {
    //公司每个人都有名称
    protected String name = "";
    //公司每个人都职位
    protected String position = "";
    //公司每个人都有薪水
    protected int salary =0;

    public Corp(String name, String position, int salary) {
        this.name = name;
        this.position = position;
        this.salary = salary;
    }

    //获得员工信息
    public abstract void getInfo();
}

/**
 * 这些树枝节点也就是这些领导们既要有自己的信息,还要知道自己的下属情况
 */
public class Branch extends Corp{
    //领导下边有那些下级领导和小兵
    private List<Corp> subordinateList;

    private Integer level;

    //构造函数是必须的了
    public Branch(String name, String position, int salary,Integer level) {
        super(name, position, salary);
        this.level=level;
       this.subordinateList = new ArrayList<>();

    }

    //增加一个下属,可能是小头目,也可能是个小兵
    public void addSubordinate(Corp corp) {
        this.subordinateList.add(corp);
    }


    @Override
    public void getInfo() {

        String info = "";
        info = "姓名:" + this.name;
        info = info + "\t职位:"+ this.position;
        info = info + "\t薪水:" + this.salary;
        System.out.println(info);
        for (Corp corp : this.subordinateList) {
            //控制显示格式
            if(this.level != null){
                for (int i = 0; i < this.level; i++) {
                    //打印空格控制格式
                    System.out.print("   ");
                }
                for (int i = 0; i <this.level; i++) {
                    if( i == 0){
                        System.out.print("+");
                    }
                    System.out.print("_");
                }
            }
            //打印名称
            corp.getInfo();
        }
    }
}


/**
 * 普通员工很简单,就写一个构造函数就可以了
 */
public class Leaf extends Corp{

    public Leaf(String name, String position, int salary) {
        super(name, position, salary);
    }

    //获得员工信息
    @Override
    public void getInfo(){
        String info = "";
        info = "姓名:" + this.name;
        info = info + "\t职位:"+ this.position;
        info = info + "\t薪水:" + this.salary;
        System.out.println(info);
    }
}



/**
 * 组装这个树形结构,并展示出来
 */
public class Client {
    public static void main(String[] args) {
        //首先是组装一个组织结构出来
        Branch ceo = compositeCorpTree();

        //首先把CEO的信息打印出来:
        ceo.getInfo();
        //然后是所有员工信息
        //System.out.println(getTreeInfo(ceo));
    }

    //把整个树组装出来
    public static Branch compositeCorpTree() {
        //首先产生总经理CEO
        Branch root = new Branch("王大麻子", "总经理", 100000,1);
        //把三个部门经理产生出来
        Branch developDep = new Branch("刘大瘸子", "研发部门经理", 10000,2);
        Branch salesDep = new Branch("马二拐子", "销售部门经理", 20000,2);
        Branch financeDep = new Branch("赵三驼子", "财务部经理", 30000,2);

        //再把三个小组长产生出来
        Branch firstDevGroup = new Branch("杨三乜斜", "开发一组组长", 5000,3);
        Branch secondDevGroup = new Branch("吴大棒槌", "开发二组组长", 6000,3);

        //把所有的小兵都产生出来
        Leaf a = new Leaf("a", "开发人员", 2000);
        Leaf b = new Leaf("b", "开发人员", 2000);
        Leaf c = new Leaf("c", "开发人员", 2000);
        Leaf d = new Leaf("d", "开发人员", 2000);
        Leaf e = new Leaf("e", "开发人员", 2000);
        Leaf f = new Leaf("f", "开发人员", 2000);
        Leaf g = new Leaf("g", "开发人员", 2000);
        Leaf h = new Leaf("h", "销售人员", 5000);
        Leaf i = new Leaf("i", "销售人员", 4000);
        Leaf j = new Leaf("j", "财务人员", 5000);
        Leaf k = new Leaf("k", "CEO秘书", 8000);
        Leaf zhengLaoLiu = new Leaf("郑老六", "研发部副经理", 20000);

        //开始组装
        //CEO下有三个部门经理和一个秘书

        root.addSubordinate(k);
        root.addSubordinate(developDep);
        root.addSubordinate(salesDep);
        root.addSubordinate(financeDep);


        //研发部经理
        developDep.addSubordinate(zhengLaoLiu);
        developDep.addSubordinate(firstDevGroup);
        developDep.addSubordinate(secondDevGroup);


        //看看开发两个开发小组下有什么
        firstDevGroup.addSubordinate(a);
        firstDevGroup.addSubordinate(b);
        firstDevGroup.addSubordinate(c);
        secondDevGroup.addSubordinate(d);
        secondDevGroup.addSubordinate(e);
        secondDevGroup.addSubordinate(f);

        //再看销售部下的人员情况
        salesDep.addSubordinate(h);
        salesDep.addSubordinate(i);

        //最后一个财务
        financeDep.addSubordinate(j);

        return root;
    }
}



运行结果:
姓名:王大麻子	职位:总经理	薪水:100000
   +_姓名:k	职位:CEO秘书	薪水:8000
   +_姓名:刘大瘸子	职位:研发部门经理	薪水:10000
      +__姓名:郑老六	职位:研发部副经理	薪水:20000
      +__姓名:杨三乜斜	职位:开发一组组长	薪水:5000
         +___姓名:a	职位:开发人员	薪水:2000
         +___姓名:b	职位:开发人员	薪水:2000
         +___姓名:c	职位:开发人员	薪水:2000
      +__姓名:吴大棒槌	职位:开发二组组长	薪水:6000
         +___姓名:d	职位:开发人员	薪水:2000
         +___姓名:e	职位:开发人员	薪水:2000
         +___姓名:f	职位:开发人员	薪水:2000
   +_姓名:马二拐子	职位:销售部门经理	薪水:20000
      +__姓名:h	职位:销售人员	薪水:5000
      +__姓名:i	职位:销售人员	薪水:4000
   +_姓名:赵三驼子	职位:财务部经理	薪水:30000
      +__姓名:j	职位:财务人员	薪水:5000

组合模式在源码中的应用

  1. Java 的集合类-HashMap 就使用了组合模式,他里面有一个putAll()方法
  2. ArrayList也有addAll()方法,他也用了组合模式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值