博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式梳理——组合模式
阅读量:4096 次
发布时间:2019-05-25

本文共 4195 字,大约阅读时间需要 13 分钟。

概述

       组合模式(Composite),也称为 整体-部分(Part-Whole)模式,它的宗旨是通过将单个对象(叶子节点)和组合对象(树枝节点)用相同的接口进行表示,使得客户对单个对象和组合对象的使用具有一致性。

一般用来描述 整体部分 的关系,它将对象组织到树形结构中,最顶层的节点称为 根节点,根节点下面可以包含 树枝节点叶子节点,树枝节点下面又可以包含 树枝节点叶子节点。如下图所示:

        由上图可以看出,其实 根节点树枝节点 本质上是同一种数据类型(蓝色圆圈),可以作为容器使用;而 叶子节点树枝节点 在语义上不属于同一种类型,但是在 中,会把 树枝节点叶子节点 认为是同一种数据类型(用同一接口定义),让它们具备一致行为。这样,在 中,整个树形结构中的对象都是同一种类型,带来的一个好处就是客户无需辨别 树枝节点 还是 叶子节点,而是可以直接进行操作,给客户使用带来极大的便利。

核心:借助同一接口,使叶子节点和树枝节点的操作具备一致性。

主要解决

        当子系统与其内各个对象层次呈现树形结构时,可以使用 让该子系统内各个对象层次的行为操作具备一致性。客户端使用该子系统内任意一个层次对象时,无须进行区分,直接使用通用操作即可,为客户端的使用带来了便捷。

:如果树形结构系统不使用 进行架构,那么按照正常的思维逻辑,对该系统进行职责分析,按上文树形结构图所示,该系统具备两种对象层次类型:树枝节点和叶子节点。那么我们就需要构造两种对应的类型,然后由于树枝节点具备容器功能,因此树枝节点类内部需维护多个集合存储其他对象层次(eg:List<Composite>,List<Leaf>),如果当前系统对象层次更复杂时,那么树枝节点内就又要增加对应的层次集合,这对树枝节点的构建带来了巨大的复杂性,臃肿性以及不可扩展性。同时客户端访问该系统层次时,还需进行层次区分,这样才能使用对应的行为,给客户端的使用也带来了巨大的复杂性。而如果使用 构建该系统,由于 抽取了系统各个层次的共性行为,具体层次只需按需实现所需行为即可,这样子系统各个层次就都属于同一种类型,所以树枝节点只需维护一个集合(List<Component>)即可存储系统所有层次内容,并且客户端也无需区分该系统各个层次对象,对内系统架构简洁优雅,对外接口精简易用。

优缺点

优点

  • 屏蔽了对象系统的层次差异性(树节点和叶子节点为不同类型),将客户代码与复杂的容器对象解耦,使得客户端可以忽略层次间的差异,使用一致的行为控制不同层次。
  • 在 可以很方便地增加 树枝节点叶子节点 对象,并对现有类库无侵入,符合 开闭原则

缺点

  • 如果类系统(树形结构)过于庞大,虽然对不同层次都提供一致性操作,但客户端仍需花费时间理清类之间的层次关系;
  • 在具体实现上违背了设计模式 接口隔离原则依赖倒置原则

使用场景

  • 系统对象层次具备整体和部分,呈树形结构,且要求具备统一行为(如树形菜单,操作系统目录结构,公司组织架构等);

模式讲解

主要包含三种角色:

  • 抽象根节点(Component):定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性;
  • 树枝节点(Composite):定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构;
  • 叶子节点(Leaf):叶子节点对象,其下再无分支,是系统层次遍历的最小单位;

UML图示

代码实现

1、公司类(抽象类或接口),component

public abstract class Company {    private String name;    public Company(String name) {        this.name = name;    }    public abstract void add(Company company);    public abstract void remove(Company company);    public abstract void display(int depth);}

2、具体公司类(树枝节点)

public class ConcreteCompany extends Company {    private List
childreList = new ArrayList<>(); private String name; public ConcreteCompany(String name) { super(name); this.name = name; } @Override public void add(Company company) { childreList.add(company); } @Override public void remove(Company company) { childreList.remove(company); } @Override public void display(int depth) { StringBuilder stringBuilder = new StringBuilder(); for (int i=0;i

3、人力部(叶节点)

private String name;    public HRDepartment(String name) {        super(name);        this.name = name;    }    @Override    public void add(Company company) {    }    @Override    public void remove(Company company) {    }    @Override    public void display(int depth) {        StringBuilder stringBuilder = new StringBuilder();        for (int i=0;i

4、财务部(叶节点)

public class FinanceDepartment extends Company {    private String name;    public FinanceDepartment(String name) {        super(name);        this.name = name;    }    @Override    public void add(Company company) {    }    @Override    public void remove(Company company) {    }    @Override    public void display(int depth) {        StringBuilder stringBuilder = new StringBuilder();        for (int i=0;i

5、测试类

public class Test {    public static void main(String[] args) {        ConcreteCompany root = new ConcreteCompany("北京总公司");        root.add(new HRDepartment("总公司人力资源部"));        root.add(new FinanceDepartment("总公司财务部"));        ConcreteCompany composite = new ConcreteCompany("上海华东分公司");        composite.add(new HRDepartment("华东分公司人力资源部"));        composite.add(new FinanceDepartment("华东分公司财务部"));        root.add(composite);        ConcreteCompany composite1 = new ConcreteCompany("南京办事处");        composite1.add(new HRDepartment("南京办事处人力资源部"));        composite1.add(new FinanceDepartment("南京办事处财务部"));        composite.add(composite1);        ConcreteCompany composite2 = new ConcreteCompany("杭州办事处");        composite2.add(new HRDepartment("杭州办事处人力资源部"));        composite2.add(new FinanceDepartment("杭州办事处财务部"));        composite.add(composite2);        System.out.println("结构图:");        root.display(1);    }}输出:- 北京总公司- - - 总公司人力资源部- - - 总公司财务部- - - 上海华东分公司- - - - - 华东分公司人力资源部- - - - - 华东分公司财务部- - - - - 南京办事处- - - - - - - 南京办事处人力资源部- - - - - - - 南京办事处财务部- - - - - 杭州办事处- - - - - - - 杭州办事处人力资源部- - - - - - - 杭州办事处财务部

注:参考文献《大话设计模式》程杰著。

 

 

 

你可能感兴趣的文章
数据结构之单链表——C++模板类实现
查看>>
Linux的SOCKET编程 简单演示
查看>>
正则匹配函数
查看>>
Linux并发服务器编程之多线程并发服务器
查看>>
聊聊gcc参数中的-I, -L和-l
查看>>
[C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)
查看>>
C语言内存检测
查看>>
Linux epoll模型
查看>>
Linux select TCP并发服务器与客户端编程
查看>>
Linux系统编程——线程池
查看>>
基于Visual C++2013拆解世界五百强面试题--题5-自己实现strstr
查看>>
Linux 线程信号量同步
查看>>
C++静态成员函数访问非静态成员的几种方法
查看>>
类中的静态成员函数访问非静态成员变量
查看>>
C++学习之普通函数指针与成员函数指针
查看>>
C++的静态成员函数指针
查看>>
Linux系统编程——线程池
查看>>
yfan.qiu linux硬链接与软链接
查看>>
Linux C++线程池实例
查看>>
shared_ptr简介以及常见问题
查看>>