23种设计模式——组合模式

本文介绍组合模式的概念、特点及实现方式,通过大学—学院—专业的实例展示如何应用此模式,简化客户端代码并保持良好的扩展性。

23种设计模式——组合模式

1、组合模式概述

组合模式的定义

组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。

组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

这种类型的设计模式属于结构型模式。

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

组合模式的特点

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

在这里插入图片描述

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

这样,在组合模式中,整个树形结构中的对象都属于同一种类型,带来的好处就是用户不需要辨别是树枝节点还是叶子节点,可以直接进行操作,给用户的使用带来极大的便利。

组合模式的优缺点

优点

  1. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码;
  2. 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”;

缺点

  1. 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  2. 不容易限制容器中的构件;
  3. 不容易用继承的方法来增加构件的新功能;

2、组合模式的结构

组合模式的结构

组合模式包含以下主要角色。

  1. 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。组抽象构件还声明访问和管理子类的接口;
  2. 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件,定义了组合内元素的行为。
  3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件,但可能不具有树叶构件的某些行为。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

组合模式的结构图

在这里插入图片描述

3、组合模式的实现

完成 大学——学院——专业的展示

定义抽象构件(Component)角色:

public abstract class Component {

    private String name;
    private String des;

    public Component(String name, String des) {
        this.name = name;
        this.des = des;
    }

    //增加
    protected void add(Component component){
        //抛出不支持操作的异常
        throw new UnsupportedOperationException();
    }

    //移除
    protected void remove(Component component){
        //抛出不支持操作的异常
        throw new UnsupportedOperationException();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDes() {
        return des;
    }

    public void setDes(String des) {
        this.des = des;
    }

    //抽象的打印方法
    protected abstract void print();

}

定义树枝构件(Composite)角色 / 中间构件1:University 大学

public class University extends Component{

    //List存放的是学院的信息
    List<Component> components =  new ArrayList<>();

    public University(String name, String des) {
        super(name, des);
    }

    @Override
    protected void add(Component component) {
        components.add(component);
    }

    @Override
    protected void remove(Component component) {
        components.remove(component);
    }


    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }

    //打印University包含的学院的名字
    @Override
    protected void print() {
        System.out.println("===============名称:"+getName()+"描述:"+getDes()+"===============");
        for (Component coms : components){
            coms.print();
        }
    }
}

定义树枝构件(Composite)角色 / 中间构件2:College 学院

public class College extends Component{

    //List存放的是专业的信息
    List<Component> components =  new ArrayList<>();

    public College(String name, String des) {
        super(name, des);
    }

    //实际业务中,University和College重写的add方法和remove方法可能不相同
    @Override
    protected void add(Component component) {
        components.add(component);
    }

    @Override
    protected void remove(Component component) {
        components.remove(component);
    }


    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }

    //打印College包含的专业的名字
    @Override
    protected void print() {
        System.out.println("===============名称:"+getName()+"描述:"+getDes()+"===============");
        for (Component coms : components){
            coms.print();
        }
    }
}

定义树叶构件(Leaf)角色:Department 专业

public class Department extends Component{

    public Department(String name, String des) {
        super(name, des);
    }

    @Override
    public String getName() {
        return super.getName();
    }

    @Override
    public String getDes() {
        return super.getDes();
    }

    @Override
    protected void print() {
        System.out.println("名称:"+getName()+"描述:"+getDes());
    }
}

编写测试类进行测试:

public class Client {

    public static void main(String[] args) {

        //创建大学
        Component university = new University("清华大学", "非常好的大学");

        //创建学院
        Component college1 = new College("信息工程学院", "信息工程学院好多专业");
        Component college2 = new College("建设工程学院", "建设工程学院好多专业");

        //将学院添加到学校中
        university.add(college1);
        university.add(college2);

        //创建专业,并把专业添加到学院中
        college1.add(new Department("计算机科学与技术","计算机科学与技术好专业"));
        college1.add(new Department("网络工程","网络工程好专业"));
        college2.add(new Department("土木","土木好专业"));
        college2.add(new Department("测绘","测绘好专业"));

        university.print();
    }
}

在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

万里顾—程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值