6.7 组合模式(Composite Pattern)

一. 定义

在现实生活中存在很多 “部分-整体”的关系.如大学中的部门与学院,文件系统中的文件与文件夹,对这些对象的处理,可用组合模式实现。

1>又叫部分整体(Part-Whole)模式,它是一种将对象组合成树状的层次结构,以表示"整体-部分"的层次关系;

2>这种类型的设计模式属于结构型模式;

3>组合模式使得客户端对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象;

二. 特点

由上图可以看出,其根节点和树枝节点本质上属于同一种数据类型,可以作为容器使用,而叶子节点与树枝节点在语义上不属于同一种类型,但是在组合模式中,会把树枝节点和叶子节点看作属于同一种数据类型(用统一接口定义),让他们具备一致行为。使得用户不用辨别,可直接操作。

1. 优点

1>简化客户端操作,客户端只需面对一致的对象而不用考虑整体部分或节点叶子的问题;

2>具有较强的扩展性,当我们更改组合对象时,我们只需要调整内部的层次关系,客户端不用做出任何改动;

3>方便创建复杂的层次结构,客户端不用理会组合里面的组织细节,容易添加节点或叶子从而创建出复杂的树形结构;

2. 缺点

要求较高的抽象性,如节点和叶子有很多差异性的话,比如很多方法和属性不一样,不适合使用组合模式;

三. 应用场景

1.需要遍历组织机构,或处理的对象具有树形结构时,非常适合使用组合模式;

2.需求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。

3.使用组合模式需要确保有相似方法及属性的几个对象,不如这里的学校,学院就有相似的输出方法;

四. 模式的结构

将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,以避免安全性问题,

但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。

组合模式结构图

组合模式角色分析

  1. Component(抽象构件):

为叶子节点和树枝节点声明公共接口,并实现它们的默认行为, 在透明式的组合中抽象构件还声明访问和管理子类的接口;

在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝结点完成(总的抽象类定义一些通用的方法:新增、删除)。

  1. Leaf(叶子节点):作为被管理者无子节点不能管理孩子,但它定义了组合内元素的行为;

  2. Composite(树枝结点):可存储和管理叶子和子节点,但不具叶子的某些行为,通常包含add(),remove(),getChild()等方法;

五. 模式的实现

假如要访问集合 c0={leaf1,{leaf2,leaf3}} 中的元素,其对应的树状图如图 3 所示。

需求:解决学校院系展示存在的问题

编程展示一个学校院系结构,要在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系,关系如下:

------清华大学-----

-----计算机学院-----

软件工程

网络工程

-----信息工程学院----

通信工程

信息工程

1.传统方案解决

将学院看做是学校的子类,系是学院的子类,这样实际上是站在组织大小的维度进行分层的;

实际上我们要求在一个页面中展示出学校的院系组成,一个学校有多个学院,一个学院有多个系,因此这种方案,不能很好实现 管理操作,比如对学院,系的添加,删除,遍历等;

2.使用组合模式解决

把学校、院、系都看做是组织结构,它们之间没有继承的关系,而是一个树形结构,可更好的实现 管理操作;

1> 实例结构图

2> 相关代码实现

public class CompositeClient {
    public static void main(String[] args) {
        //从大到小创建对象 学校
        University university = new University("清华大学");


        //创建学院
        Collage ComputerCollage = new Collage("计算机学院");
        Collage InfoEngineerCollage = new Collage("信息工程学院");


        //创建计算机学院下的系
        ComputerCollage.add(new Department("软件工程系"));
        ComputerCollage.add(new Department("网络工程系"));


        //创建信息工程学院下的系
        InfoEngineerCollage.add(new Department("通信工程系"));
        InfoEngineerCollage.add(new Department("信息工程系"));


        //将学院加入到学校中
        university.add(ComputerCollage);
        university.add(InfoEngineerCollage);
        university.print();
    }
}
//Component 抽象构件
public abstract class Component {
    protected String name;
    public Component(String name) {
        this.name = name;
    }
    //由子类来实现
    protected abstract void print();
}
//University 就是 Composite,可以管理College
public class University extends Component {
    //存放的是Collage
    private List<Component> components = new ArrayList<>();
    public University(String name) {
        super(name);
    }
    protected void add(Component component) {
        components.add(component);
    }
    protected void remove(Component component) {
        components.remove(component);
    }
    @Override //输出University 中包含的学院
    protected void print() {
        System.out.println("--------"+name+"---------");
        //遍历organizationComponents
        for (Component component : components) {
            component.print();
        }
    }
}
//Collage 学院 也是 Composite,可以管理department
public class Collage extends Component {
    //存放的是department(系)
    private List<Component> components = new ArrayList<>();
    //构造器
    public Collage(String name) {
        super(name);
    }
    protected void add(Component component) {
        //将来实际业务中 Collage的add 和 University add不一定相同
        components.add(component);
    }
    protected void remove(Component component) {
        components.remove(component);
    }
    @Override //输出Collage 中包含的系
    protected void print() {
        System.out.println("--------"+name+"---------");
        //遍历organizationComponents
        for (Component component : components) {
            component.print();
        }
    }
}// Leaf 树叶构件 系
public class Department extends Component{
    public Department(String name) {
        super(name);
    }
    @Override
    protected void print() {
        System.out.println("--------"+name+"---------");//所在系的名字
    }
}

程序运行结果

--------清华大学---------
--------计算机学院---------
--------软件工程系---------
--------网络工程系---------
--------信息工程学院---------
--------通信工程系---------
--------信息工程系---------

3. JDK源码运用

//AbstractMap 相当于Component  HashMap相当于Composite  Node相当于 Leaf
Map<Integer, String> hashMap = new HashMap<>();
hashMap.put(1, "mm");
hashMap.put(2, "mk");
hashMap.putAll(hashMap);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值