软件设计模式之路-----组合模式

组合模式跟面向对象啊设计中的"组合关系"是两码事。组合模式设计,主要用来处理树形结构数据。

组合模式的定义:有时又叫作整体-部分(Part-Whole)模式,它是一种将对象组合成树状的层次结构的模式,用来表示“整体-部分”的关系,使用户对单个对象和组合对象具有一致的访问性,属于结构型设计模式。

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

这样的好处是客户端不需要分辨是节点类型,可以统一操作。

优点:

  • 客户端可以一致处理单个对象和组合对象
  • 更容易在组合体内加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足“开闭原则”

缺点:

  • 设计较复杂,客户端需要花更多时间理清类之间的层次关系;
  • 应用场景比较局限

组合模式的结构与实现

结构:

  1. 抽象构件(Component)角色:它的主要作用是为树叶构件和树枝构件声明公共接口,并实现它们的默认行为。在透明式的组合模式中抽象构件还声明访问和管理子类的接口;在安全式的组合模式中不声明访问和管理子类的接口,管理工作由树枝构件完成。(总的抽象类或接口,定义一些通用的方法,比如新增、删除) 
  2. 树叶构件(Leaf)角色:是组合中的叶节点对象,它没有子节点,用于继承或实现抽象构件。 
  3. 树枝构件(Composite)角色 / 中间构件:是组合中的分支节点对象,它有子节点,用于继承和实现抽象构件。它的主要作用是存储和管理子部件,通常包含 Add()、Remove()、GetChild() 等方法。

实现:

实现场景:文件夹与文件

文件夹结构如图

package com.wly.DesignPatterns;

import java.util.ArrayList;

/**
 * @program: StudyDome
 * @author: yuanzhang
 * @create: 2020-12-24 11:41
 **/
public class CompositePattern{
    public static void main(String[] args) {
        Folder folder = new PaperFile("一级目录");
        Folder folder1 = new PaperFile("二级目录A");
        Folder folder2 = new PaperFile("二级目录B");
        Folder file = new File("目录A内文件夹AA");
        Folder file1 = new File("目录B内文件夹BB");
        Folder file2 = new File("目录B内文件夹BC");
        folder.add(folder1);
        folder.add(folder2);
        folder1.add(file);
        folder2.add(file1);
        folder2.add(file2);
        System.out.println("查看一级目录内的内容-----------------");
        folder.lookOver();
        System.out.println("查看二级目录A内的内容----------------");
        folder1.lookOver();
        System.out.println("查看二级目录B内的内容----------------");
        folder2.lookOver();
    }

}
/** 
 * @Annotation:抽象构件:目录
 * @Author: yuanzhang
 * @Date:  14:11
 */ 
abstract class Folder{
    protected String name;

    protected   Folder(String name){
        this.name = name;
    }
    protected  abstract void   add(Folder folder);
    protected  abstract void remove(Folder folder);
    protected  abstract Folder getChild(int i);
    protected  abstract void lookOver();
}
/** 
 * @Annotation:树叶构建:文件
 * @Author: yuanzhang
 * @Date:  14:16
 */ 
class File extends Folder{

    protected  File(String name){
        super(name);
    }

    @Override
    protected void add(Folder folder) {
        this.name = folder.name;
    }

    @Override
    protected void remove(Folder folder) {
        folder =null;
    }

    @Override
    protected Folder getChild(int i) {
        return null;
    }

    @Override
    protected void lookOver() {
        System.out.println("文件名:"+name);
    }
}
/** 
 * @Annotation:树枝构件:根目录
 * @Author: yuanzhang
 * @Date:  14:12
 */ 
class PaperFile extends Folder{


    private ArrayList<Folder> fileList = new ArrayList <Folder>();

    protected PaperFile(String name){
        super(name);
    }
    @Override
    protected void add(Folder folder) {
        fileList.add(folder);
    }

    @Override
    protected void remove(Folder folder) {
        fileList.remove(folder);
    }

    @Override
    protected Folder getChild(int i) {
        return fileList.get(1);
    }

    @Override
    protected void lookOver() {
        for (Folder folder : fileList) {
            String title = "";
            if (folder instanceof File){
                title = "文件名";
            }
            if (folder instanceof PaperFile){
                title = "文件夹";
            }
            System.out.println(title+":"+folder.name);
        }
    }
}

输出

查看一级目录内的内容-----------------
文件夹:二级目录A
文件夹:二级目录B
查看二级目录A内的内容----------------
文件名:目录A内文件夹AA
查看二级目录B内的内容----------------
文件名:目录B内文件夹BB
文件名:目录B内文件夹BC

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值