2022-07-31 23:23阅读: 64评论: 1推荐: 0

23种设计模式之组合模式

  • 组合模式的结构
    • 组合模式的分类
      • 透明方式
      • 安全方式
    • 模式的实现
      • 透明组合模式
      • 安全组合模式


    Java技术债务

    概述

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

    它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。

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

    Java技术债务

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

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

    组合模式优缺点

    组合模式的主要优点有:

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

    其主要缺点是:

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

    组合模式的结构和实现

    组合模式的结构

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

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

    组合模式的分类

    组合模式分为透明式的组合模式和安全式的组合模式。

    透明方式

    在该方式中,由于抽象构件声明了所有子类中的全部方法,所以客户端无须区别树叶对象和树枝对象,对客户端来说是透明的。

    但其缺点是:树叶构件本来没有 Add()、Remove() 及 GetChild() 方法,却要实现它们(空实现或抛异常),这样会带来一些安全性问题。

    安全方式

    在该方式中,将管理子构件的方法移到树枝构件中,抽象构件和树叶构件没有对子对象的管理方法,这样就避免了上一种方式的安全性问题。

    但由于叶子和分支有不同的接口,客户端在调用时要知道树叶对象和树枝对象的存在,所以失去了透明性。

    模式的实现

    假如要访问集合 c0={leaf1,{leaf2,leaf3}} 中的元素

    在这里插入图片描述

    透明组合模式

    public class CompositePattern {
        public static void main(String[] args) {
            Component c0 = new Composite();
            Component c1 = new Composite();
            Component leaf1 = new Leaf("1");
            Component leaf2 = new Leaf("2");
            Component leaf3 = new Leaf("3");
            c0.add(leaf1);
            c0.add(c1);
            c1.add(leaf2);
            c1.add(leaf3);
            c0.operation();
        }
    }
    //抽象构件
    interface Component {
        public void add(Component c);
        public void remove(Component c);
        public Component getChild(int i);
        public void operation();
    }
    //树叶构件
    class Leaf implements Component {
        private String name;
        public Leaf(String name) {
            this.name = name;
        }
        public void add(Component c) {
        }
        public void remove(Component c) {
        }
        public Component getChild(int i) {
            return null;
        }
        public void operation() {
            System.out.println("树叶" + name + ":被访问!");
        }
    }
    //树枝构件
    class Composite implements Component {
        private ArrayList<Component> children = new ArrayList<Component>();
        public void add(Component c) {
            children.add(c);
        }
        public void remove(Component c) {
            children.remove(c);
        }
        public Component getChild(int i) {
            return children.get(i);
        }
        public void operation() {
            for (Object obj : children) {
                ((Component) obj).operation();
            }
        }
    }
    

    结果如下:

    树叶1:被访问!
    树叶2:被访问!
    树叶3:被访问!
    

    安全组合模式

    安全式的组合模式与透明式组合模式的实现代码类似,只要对其做简单修改就可以了,代码如下。

    首先修改 Component 代码,只保留层次的公共行为。

    interface Component {
        public void operation();
    }
    

    然后修改客户端代码,将树枝构件类型更改为 Composite 类型,以便获取管理子类操作的方法。

    public class CompositePattern {
        public static void main(String[] args) {
            Composite c0 = new Composite();
            Composite c1 = new Composite();
            Component leaf1 = new Leaf("1");
            Component leaf2 = new Leaf("2");
            Component leaf3 = new Leaf("3");
            c0.add(leaf1);
            c0.add(c1);
            c1.add(leaf2);
            c1.add(leaf3);
            c0.operation();
        }
    }
    

    总结

    优点: 1、高层模块调用简单。 2、节点自由增加。

    缺点: 在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则。

    使用场景: 部分、整体场景,如树形菜单,文件、文件夹的管理。

    注意事项: 定义时为具体类。

    更多请移驾。。。

    🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

    本文作者:Java技术债务
    原文链接:https://www.cuizb.top/myblog/article/1658760403
    版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。

    🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽🔽

    Java技术债务
    JVM内存泄漏和内存溢出的原因
    JVM常用监控工具解释以及使用
    Redis 常见面试题(一)
    ClickHouse之MaterializeMySQL引擎(十)
    三种实现分布式锁的实现与区别
    线程池的理解以及使用

    号外!号外!

    最近面试BAT,整理一份面试资料,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。想获取吗?如果你想提升自己,并且想和优秀的人一起进步,感兴趣的朋友,可以在扫码关注下方公众号。资料在公众号里静静的躺着呢。。。

    Java技术债务

    • 喜欢就收藏
    • 认同就点赞
    • 支持就关注
    • 疑问就评论

    一键四连,你的offer也四连

    posted @   Java技术债务  阅读(64)  评论(1编辑  收藏  举报
    点击右上角即可分享
    微信分享提示
    💬
    评论
    📌
    收藏
    💗
    关注
    👍
    推荐
    🚀
    回顶
    收起
    1. 1 404 not found REOL
    404 not found - REOL
    00:00 / 00:00
    An audio error has occurred.