• 【设计模式】组合模式



    在这里插入图片描述

    主页传送门:💁 传送

    1.组合模式定义

           组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。

    Compose objects into tree structure to represent part-whole hierarchies.Composite lets client treat individual objects and compositions of objects uniformly.

           即:将对象组合成树形结构以表示 “部分-整体” 的层次结构,使得用户对单个对象和组合对象的使用具有一致性。

    2.组合模式的结构

    组合模式的实现根据所实现接口的区别分为两种形式,分别称为安全式和透明式。

    2.1. 安全式组合模式的结构

    安全模式的组合模式要求管理聚集的方法只出现在树枝构件类中,而不出现在树叶构件类中。
    在这里插入图片描述
      这种形式涉及到三个角色:

    • 抽象构件(Component)角色: 这是一个抽象角色,它给参加组合的对象定义出公共的接口及其默认行为,可以用来管理所有的子对象。合成对象通常把它所包含的子对象当做类型为Component的对象。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝构件对象给出。

    • 树叶构件(Leaf)角色: 树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。

    • 树枝构件(Composite)角色: 代表参加组合的有下级子对象的对象。树枝构件类给出所有的管理子对象的方法,如add()、remove()以及getChild()。

    安全式组合模式的缺点是不够透明,因为树叶类和树枝类将具有不同的接口。

    2.2.透明式组合模式的结构

    与安全式的组合模式不同的是,透明式的组合模式要求所有的具体构件类,不论树枝构件还是树叶构件,均符合一个固定接口。
    在这里插入图片描述

    3.组合模式实战案例

    3.1.场景说明

           设计一个文件系统的杀毒软件,文件系统可以分为文件夹和文件,文件又分为文本文件,图片文件,视频文件。

    3.2.关系类图

           使用组合模式来实现的结构图如下:
    在这里插入图片描述

    3.3.代码实现

    //Component 抽象构件

    /**
     * 抽象文件类:抽象构件接口
     */
    interface File {
        /**
         * 默认方法
         * @param file
         */
        public default void add(File file) {
            throw new RuntimeException("reject");
        }
        public default void remove(File file) {
            throw new RuntimeException("reject");
        }
        public default File getChild(int index) {
            throw new RuntimeException("reject");
        }
        void killVirus();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    //Leaf 叶子构件

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * 图像文件类:叶子构建
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class ImageFile implements File {
    
        private String name;
    
        @Override
        public void killVirus() {
            System.out.println("---对图像文件:" + name + "正在杀毒!");
        }
    }
    
    /**
     * 文本文件类:叶子构件
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class TextFile implements File {
        private String name;
    
        @Override
        public void killVirus() {
            System.out.println("---对文本文件:" + name + "正在杀毒!");
        }
    }
    
    /**
     * 视频文件类:叶子构建
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class VideoFile implements File {
        private String name;
    
        @Override
        public void killVirus() {
            System.out.println("---对视频文件:" + name + "正在杀毒!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    //Composite 容器构件

    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * 文件夹类:容器构件
     */
    class Folder implements File {
    
        /**
         * 存储File类型的成员
         */
        private List<File> fileList = new ArrayList<>();
        private String name;
    
        public Folder(String name) {
            this.name = name;
        }
    
        @Override
        public void add(File file) {
            this.fileList.add(file);
        }
    
        @Override
        public void remove(File file) {
            this.fileList.remove(file);
        }
    
        @Override
        public File getChild(int index) {
            return this.fileList.get(index);
        }
    
        @Override
        public void killVirus() {
            System.out.println("---对文件夹:" + name + "进行杀毒!");
            for (File file : fileList) {
                file.killVirus();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    // 场景类

    /**
     * 组合模式案例
     * @author Liucheng
     * @since 2019-07-26
     */
    public class Client {
    
        public static void main(String[] args) {
    
            File folder1 = new Folder("Sunny的资料");
            File folder2 = new Folder("图像文件");
            File folder3 = new Folder("文本文件");
            File folder4 = new Folder("视频文件");
    
            File file1 = new ImageFile("小龙女.jpg");
            File file2 = new ImageFile("张无忌.gif");
            File file3 = new TextFile("九阴真经.txt");
            File file4 = new TextFile("葵花宝典.doc");
            File file5 = new VideoFile("笑傲江湖.rmvb");
    
            folder2.add(file1);
            folder2.add(file2);
            folder3.add(file3);
            folder3.add(file4);
            folder4.add(file5);
            folder1.add(folder2);
            folder1.add(folder3);
            folder1.add(folder4);
    
            //从“Sunny的资料”节点开始进行杀毒操作
            folder1.killVirus();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    4.组合模式优缺点

    组合模式是一种结构型设计模式,它允许将对象组合成树状的层次结构,以表示“整体-部分”的关系。组合模式的优点和缺点如下:

    优点:

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

    缺点:

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

    5.组合模式适用场景

    组合模式适用于以下场景:

    1. 表示递归结构:组合模式适合用于表示树形或递归结构,例如文件系统、组织结构等,这些场景中需要对单个对象和组合对象进行一致处理。
    2. 客户端希望忽略差异:当客户端希望忽略组合对象与单个对象的差异时,可以使用组合模式,例如,客户端只需要对整个层次结构进行控制,而不关心具体的单个对象。
    3. 处理树形结构:组合模式适用于处理树形结构,需要对层次进行定义、忽略层次差异、简化客户端代码等。

    总之,组合模式适用于处理树形结构或递归结构的场景,当客户端希望忽略差异、简化代码或符合开闭原则时,可以选择使用组合模式。同时需要注意其缺点,如设计复杂、不容易限制容器中的构件等。

    6.组合模式总结

         组合模式是一种设计模式,旨在将对象组合成树形结构以表示“部分-整体”的层次结构。它允许客户端代码以一致的方式处理对象和对象容器,无需关心处理的单个对象还是组合的对象容器。
         总之,组合模式是一种有用的设计模式,可以在适当的情况下应用来简化客户端代码、降低耦合度和提高可扩展性。然而,它也有一些缺点和适用场景需要注意和考虑。

    如果喜欢的话,欢迎 🤞关注 👍点赞 💬评论 🤝收藏 🙌一起讨论
    你的支持就是我✍️创作的动力! 💞💞💞

  • 相关阅读:
    【前端攻城师之JS基础】03函数进阶
    【阿里云X博客园】参与征文赢面试绿通资格!还有特别福利哦!
    torch.mean()、tensor.mean() 用法及维度的理解(二维、三维)
    数据结构Map-Set和哈希表
    记一次线上环境排查错误过程
    亚马逊、速卖通、Lazada、Shopee、eBay、wish、沃尔玛、阿里国际、美客多等跨境电商平台,测评自养号该如何利用产品上新期抓住流量?
    【矩阵理论常见符号说明】
    java程序员进阶必读书单
    10行代码实现RSA公钥解密
    数据面最流行的工具包dpdk的前世-现在和未来
  • 原文地址:https://blog.csdn.net/hm973046/article/details/133199411