【编程素质】组合模式(Composite Pattern、合成模式、部分整体模式)

1,概念

允许将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
树节点可以对子节点进行增删改查等操作。

1)举例

linux文件系统。

2,场景

1)需要描述对象的部分和整体之间的等级结构关系,如树形菜单、文件和文件夹管理等等
2)需要客户端忽略个体和组合构件的区别,平等对待所有的构件。

组合模式在java和android源码中也是有不少的应用的,比如List框架,就用到了组合模式原理,实现了增删改查功能,局部和个体的各种操作都可以实现。

3,实现

1)类图

①安全模式

这里写图片描述把树枝节点和树叶节点彻底分开,树枝节点单独拥有用来组合的方法,这种方法比较安全。但由于不够透明,所以树叶节点和树枝节点将不具有相同的接口,客户端的调用需要做相应
的判断,带来了不便。

②透明模式

在这里插入图片描述
把组合使用的方法放到抽象类中,不管叶子对象还是树枝对象都有相同的结构,这样做的好处就是叶子节点和树枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为Leaf
类本身不具备add()、remove()方法的功能,所以实现它是没有意义的。

2)三种角色

①抽象组件(Component)角色

该角色定义参加组合的对象的共有方法和属性,规范一些默认的行为接口。

②叶子构件(Leaf)角色

该角色是叶子对象,其下没有其他的分支,定义出参加组合的原始对象的行为。

③树枝构件(Composite)角色

该角色代表参加组合的、其下有分支的树枝对象,它的作用是将树枝和叶子组合成一个树形结构,并定义出管理子对象的方法,如add()、remove()等等。

3)demo

①抽象类:Company

/**
 * 公司的抽象类,也可以写成接口.
 */
public abstract class Company {

    ArrayList<Company> companyArrayList = new ArrayList<>();
    String name;//姓名
    String sex;//性别
    String position;//职位
    int salary;//薪水

    //获取信息
    public abstract String getInfo();

}

②树节点类:ConcreteCompany

/**
 * 树节点类,可以对分支节点进行增删改查等操作
 */
public class ConcreteCompany extends Company {



    //构造函数,这里创建的是一个树节点,但是也是有支节点的基本属性
    public ConcreteCompany(String name, String sex, String posion, int salary) {
        this.name = name;
        this.sex = sex;
        this.position = posion;
        this.salary = salary;
    }


    /**
     * 增加:添加应给支节点
     * <p>
     * 这里看起来是添加Company接口对象,但是你后面用子类的实例化,实际添加的就是子类的实例
     */
    public void add(Company company) {
        companyArrayList.add(company);
    }

    /**
     * 删除:删除某一个节点数据
     * <p>
     * 当然你也可多加其他的删除功能,你让删除某一类,或删除全部子节点数据等等
     */
    public void remove(Company company) {
        companyArrayList.remove(company);
    }

    /**
     * 查询所有子节点的数据
     * 返回的是子节点集合对象
     */
    public ArrayList<Company> getChild() {
        return companyArrayList;

    }


    //修改这里就不做了,有兴趣可以高一下

    /**
     * 树节点本身属性数据
     */
    @Override
    public String getInfo() {
        String info = "领导:  名称:" + name + ", 性别:" + sex + ", 职位:" + position + ", 薪水:" + salary;
        return info;
    }
}

③叶子节点类:Employee

/**
 * 叶子节点类
 * 被上级的树节点管理
 * 这里叶子节点没有什么权力,只能创建自己和看看自己的信息
 */
public class Employee extends Company {


    //构造函数,这里创建的是一个叶子节点,并设置基本属性
    public Employee(String name, String sex, String posion, int salary) {
        this.name = name;
        this.sex = sex;
        this.position = posion;
        this.salary = salary;
    }


    /**
     * 叶子节点本身属性数据
     */
    @Override
    public String getInfo() {
        String info = "下属:   名称:" + name + ", 性别:" + sex + ", 职位:" + position + ", 薪水:" + salary;
        return info;
    }
}

④组合模式测试类:CompositeDemo

/**
 * 组合模式的使用示例
 */
public class CompositeDemo {

    public static void main(String[] arg) {

        //CEO
        ConcreteCompany root = new ConcreteCompany("李文志", "男", "CEO", 100 * 1000);

        //部门经理,既是树节点,也是上级的子节点
        ConcreteCompany developDep = new ConcreteCompany("卢康", "男", "研发部经理", 10 * 1000);
        ConcreteCompany salesDep = new ConcreteCompany("蔡良梁", "男", "销售经理", 11 * 1000);
        ConcreteCompany finaceDep = new ConcreteCompany("习伟", "男", "财务经理", 12 * 1000);

        //把三个经理添加到公司框架中
        root.add(developDep);
        root.add(salesDep);
        root.add(finaceDep);

        //部门员工
        Employee e1 = new Employee("A", "男", "研发部", 6000);
        Employee e2 = new Employee("B", "男", "研发部", 6000);
        Employee e3 = new Employee("C", "男", "研发部", 6000);
        Employee e4 = new Employee("D", "男", "销售部", 6000);
        Employee e5 = new Employee("E", "男", "销售部", 6000);
        Employee e6 = new Employee("F", "男", "销售部", 6000);
        Employee e7 = new Employee("G", "男", "财务部", 6000);
        Employee e8 = new Employee("H", "男", "财务部", 6000);

        //把底层员工添加到特定的区域
        developDep.add(e1);//研发部门
        developDep.add(e2);
        developDep.add(e3);
        salesDep.add(e4);//销售部门
        salesDep.add(e5);
        salesDep.add(e6);
        finaceDep.add(e7);//财务部门
        finaceDep.add(e8);


        //公司的框架已经完成,并添加如数据
        //可以进行后续的操作

        System.out.println("" + root.getInfo());//查询最大的Boss情况

        display(root);//查询整个公司所有人员的情况,所有子节点的数据

    }

    //遍历打印数据
    private static void display(ConcreteCompany root) {
        for (Company c : root.getChild()) {
            if (c instanceof Employee) {//如果节点类型是子节点
                System.out.println(c.getInfo());//查询,打印

            } else {//如果节点类型是树节点
                System.out.println("\n" + c.getInfo());//查询,打印树节点
                display((ConcreteCompany) c);//再递归调用,打印里面的子节点
            }
        }
    }
}

5,Android中的应用

View和ViewGroup就是一种很标准的组合模式:
这里写图片描述
在Android的视图树中,容器一定是ViewGroup,只有ViewGroup才能包含其他View和ViewGroup。View是没有容器的。者是一种安全的组合模式。
在Android开发中用到组合模式并不很多,组合模式更多的用于界面UI的架构设计上,而这部分让开发者去实现的并不多。

4,优缺点

1)优点

①高层模块调用简单。

一棵树形机构中的所有节点都是Component,局部和整体对调用者来说没有任何区别,即高层模块不必关心自己处理的是单个对象还是整个组合结构,简化了高层模块的代码。

②节点自由增加

使用组合模式后,如果想增加树枝节点、树叶节点,只需找到父节点即可。

2)缺点

①不易控制树枝构件的类型。

②不易使用继承的方法来增加新的行为。

③违反了依赖倒置原则

在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值