设计模式-组合模式(Composite)

概述

  • 定义 : 将对象组合成树形结构以表示"部分-整体"的层次结构
  • 组合模式使客户端对单个对象和组合对象保持一致的方式处理
  • 类型 : 结构型

适用场景

  • 希望客户端可以忽略组合对象与单个对象的差异时
  • 处理一个树形结构时

优点

  • 清楚地定义分层次的复杂对象, 表示对象的全部或部分层次
  • 让客户端忽略了层次的差异, 方便对整个层次结构进行控制
  • 简化客户端代码
  • 符合开闭原则

缺点

  • 限制类型时会较为复杂
  • 使设计变得更加抽象

模式角色

  • Component

    • 为组合中的对象声明接口。

    • 在适当的情况下,实现所有类共有接口的缺省行为。

    • 声明一个接口用于访问和管理C o m p o n e n t的子组件。

    • (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。

  • Leaf

    • 在组合中表示叶节点对象,叶节点没有子节点。

    • 在组合中定义图元对象的行为。

  • Composite

    • 定义有子部件的那些部件的行为。

    • 存储子部件。

    • 在Component接口中实现与子部件有关的操作。

  • Client : 通过Component接口操纵组合部件的对象。

代码实现

场景

以最常见的操作文件和文件夹为例, 定义如下几个类

  1. FileComponent类, 对应Component角色
  2. File类,对应Leaf角色
  3. Catalog类, 对应Composite角色
  4. Client 测试类, 对应Client角色

UML类图

在这里插入图片描述

代码实现

import java.util.List;

/**
 * @author 七夜雪
 * @create 2018-11-23 19:44
 */
public abstract class FileComponent {

    public void addFile(FileComponent file){
        throw new UnsupportedOperationException("不支持新增文件操作");
    }

    public void removeFile(FileComponent file){
        throw new UnsupportedOperationException("不支持删除文件操作");
    }

    public int getSize(){
        throw new UnsupportedOperationException("不支持获取文件列表操作");
    }

    public String getName(){
        throw new UnsupportedOperationException("不支持获取文件名称操作");
    }

    // 打印文件列表或者文件名称
    public void print(){
        throw new UnsupportedOperationException("不支持打印文件操作");
    }

    public List<FileComponent> getFileList(){
        throw new UnsupportedOperationException("不支持获取文件列表操作");
    }

}
/**
 * 对应模式中Leaf角色
 *
 * @author 七夜雪
 * @create 2018-11-23 19:50
 */
public class File extends FileComponent {
    private String name;
    private int size;

    public File(String name, int size) {
        this.name = name;
        this.size = size;
    }

    @Override
    public int getSize() {
        return this.size;
    }

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

    @Override
    public void print() {
        System.out.println("文件名称 : " + this.name + "  文件大小 : " + this.size + "KB");
    }
}
/**
 * 目录类, 对应模式中Composite
 *
 * @author 七夜雪
 * @create 2018-11-23 19:54
 */
public class Catalog extends FileComponent {
    private String name;
    private Integer level;
    private List<FileComponent> list = new ArrayList<>();

    public Catalog(String name, Integer level) {
        this.name = name;
        this.level = level;
    }

    @Override
    public void addFile(FileComponent file) {
        list.add(file);
    }

    @Override
    public void removeFile(FileComponent file) {
        list.remove(file);
    }

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

    @Override
    public void print() {
        System.out.println(this.name);
        for (FileComponent fileComponent : list) {
            String space = "";
            if (level != null) {
                for (Integer i = 0; i < level; i++) {
                    space += "  ";
                }
            }
            System.out.print(space);
            fileComponent.print();
        }
    }
}

测试类 :

    public static void main(String[] args) {
        FileComponent catlog = new Catalog("D:/", 1);
        FileComponent catlog1 = new Catalog("小说", 2);
        FileComponent catlog2 = new Catalog("电影", 2);
        catlog.addFile(catlog1);
        catlog.addFile(catlog2);
        FileComponent file1 = new File("傲慢与偏见", 150);
        FileComponent file2 = new File("基督山伯爵", 1024);
        catlog1.addFile(file1);
        catlog1.addFile(file2);
        FileComponent file3 = new File("复仇者联盟", 2048 * 1024);
        FileComponent file4 = new File("战狼", 1024 * 1024);
        catlog2.addFile(file3);
        catlog2.addFile(file4);
        catlog.print();
    }

测试结果:

D:/
  小说
    文件名称 : 傲慢与偏见  文件大小 : 150KB
    文件名称 : 基督山伯爵  文件大小 : 1024KB
  电影
    文件名称 : 复仇者联盟  文件大小 : 2097152KB
    文件名称 : 战狼  文件大小 : 1048576KB

本文参考:
慕课网<java设计模式精讲 Debug 方式+内存分析>课程
四人帮<设计模式>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值