欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

“部分-整体“——组合模式

程序员文章站 2022-05-04 08:43:36
一、组合模式概述1.定义:组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。2.例子:3.分析:在树形目录结构中,包含文件和文件夹两类不同的元素。在文件夹中可以包含文件,还可以继续包含子文件夹,在文件中不能再包含子文件或者子文件夹。文件夹 —>容器(Container)文件 —>叶子(Leaf)4.理解:一致地对待容器对象和叶子对象。当容器对象的某一个方法被调用时,将遍历整个树形结构,...

一、组合模式概述

1.定义:
组合模式(Composite),将对象组合成树形结构以表示‘部分-整体’的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。

2.例子:
“部分-整体“——组合模式
3.分析:
在树形目录结构中,包含文件和文件夹两类不同的元素。
在文件夹中可以包含文件,还可以继续包含子文件夹,在文件中不能再包含子文件或者子文件夹。
文件夹 —>容器(Container)
文件 —>叶子(Leaf)

4.理解:
一致地对待容器对象和叶子对象。
当容器对象的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理
由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下客户端希望一致地处理它们,因为对于这些对象的区别对待将会使程序非常复杂
“部分-整体“——组合模式
5.结构:
组合模式包含以下3个角色:Component(抽象构件)、Leaf(叶子构件)、Composite(容器构件)

二、组合模式适用环境

1.在具有整体和部分的层次结构中,希望通过一种方式忽略整体与部分的差异,客户端可以一致地对待它们
2.在一个使用面向对象语言开发的系统中需要处理一个树形结构
3.在一个系统中能够分离出叶子对象和容器对象,而且它们的类型不固定,需要增加一些新的类型

三、组合模式案例

1.案例:
软件公司欲开发一个杀毒软件,该软件既可以对某个文件夹(Folder)杀毒,也可以对某个指定的文件(File)进行杀毒。该杀毒软件还可以根据各类文件的特点,为不同类型的文件提供不同的杀毒方式,例如图像文件(ImageFile)和文本文件(TextFile)的杀毒方式就有所差异。现使用组合模式来设计该杀毒软件的整体框架。
2.类图:
“部分-整体“——组合模式
(1) AbstractFile:抽象文件类,充当抽象构件类
(2) ImageFile:图像文件类,充当叶子构件类
(3) TextFile:文本文件类,充当叶子构件类
(4) Folder:文件夹类,充当容器构件类
(5) Client:客户端测试类
3.代码:

package composite;

/**
 * 抽象文件类,充当抽象构件类
 */
public abstract class AbstractFile {

    public abstract void add(AbstractFile file); //添加元素
    public abstract void remove(AbstractFile file); //删除元素
    public abstract void killVirus(); //模拟杀毒
}

package composite;

import java.util.ArrayList;

/**
 * 文件夹类,充当容器构件类
 */
public class Folder extends AbstractFile {

    //定义一个fileList的集合,用来存储AbstractFile类型的成员
    private ArrayList<AbstractFile> fileList = new ArrayList<>();
    private String name; //定义文件夹名

    //无参构造
    public Folder() {
    }

    //有参构造
    public Folder(String name) {
        this.name = name;
    }

    @Override
    public void add(AbstractFile file) {
        fileList.add(file);
    }

    @Override
    public void remove(AbstractFile file) {
        fileList.remove(file);
    }

    @Override
    public void killVirus() {
        System.out.println("系统正在对‘" + name + "’进行杀毒");

        //利用foreach循环对fileList集合里的所有元素进行杀毒
        for (AbstractFile abstractFile : fileList) {
            abstractFile.killVirus();
        }
    }
}

package composite;

/**
 * 图像文件类,充当叶子构件类
 */
public class ImageFile extends AbstractFile {

    private String name; //定义文件名

    //无参构造
    public ImageFile() {
    }

    //有参构造
    public ImageFile(String name) {
        this.name = name;
    }

    @Override
    public void add(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    @Override
    public void remove(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    @Override
    public void killVirus() {
        System.out.println("系统正在对‘" + name + "’进行图像杀毒");
    }
}

package composite;

/**
 * 文本文件类,充当叶子构件类
 */
public class TextFile extends AbstractFile {

    private String name; //定义文件名

    //无参构造
    public TextFile() {
    }

    //有参构造
    public TextFile(String name) {
        this.name = name;
    }

    @Override
    public void add(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    @Override
    public void remove(AbstractFile file) {
        System.out.println("对不起,不支持该方法!");
    }

    @Override
    public void killVirus() {
        System.out.println("系统正在对‘" + name + "’进行文本杀毒");
    }
}

package composite;

/**
 * 客服端测试类
 */
public class Client {

    public static void main(String[] args) {

        /*
        1.创建对象
         */
        //创建文件夹对象
        AbstractFile folder = new Folder("Bei-Zhen的资料");
        //创建子文件夹对象
        AbstractFile subfolder1 = new Folder("图像文件夹");
        AbstractFile subfolder2 = new Folder("文本文件夹");
        //创建文件对象(图像文件或文本文件)
        AbstractFile file1 = new ImageFile("百度登录流程图.jpg");
        AbstractFile file2 = new ImageFile("猜拳流程图.png");
        AbstractFile file3 = new TextFile("设计模式.txt");
        AbstractFile file4 = new TextFile("面向对象基础.doc");

        /*
        2.向集合中添加元素
         */
        //把文件添加到相对应的子文件夹中
        subfolder1.add(file1);
        subfolder1.add(file2);
        subfolder2.add(file3);
        subfolder2.add(file4);
        //把子文件夹添加到文件夹中
        folder.add(subfolder1);
        folder.add(subfolder2);

        /*
        3.对文件夹杀毒
         */
        System.out.println("---------------杀毒软件--------------------");
        System.out.println("------文件夹杀毒开始,正在闪电杀毒-----------");
        folder.killVirus();
        System.out.println("------文件夹杀毒完成,感谢你的使用-----------");
        System.out.println();

        /*
        4.对指定文件杀毒
         */
        System.out.println("------指定文件杀毒开始,正在闪电杀毒---------");
        file1.killVirus();
        System.out.println("------指定文件杀毒完成,感谢你的使用---------");

    }
}

4.代码运行截图:
“部分-整体“——组合模式

四、组合模式优缺点

1.优点:
(1)可以清楚地定义分层次的复杂对象,表示对象的全部或部分层次,让客户端忽略了层次的差异,方便对整个层次结构进行控制
(2)客户端可以一致地使用一个组合结构或其中单个对象,不必关心处理的是单个对象还是整个组合结构,简化了客户端代码
(3)增加新的容器构件和叶子构件都很方便,符合开闭原则
(4)为树形结构的面向对象实现提供了一种灵活的解决方案
2.缺点:
在增加新构件时很难对容器中的构件类型进行限制

本文地址:https://blog.csdn.net/qq_33591873/article/details/107595527

相关标签: 设计模式 java