广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java设计模式之组合模式
  • 270
分享到

Java设计模式之组合模式

2024-04-02 19:04:59 270人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在

本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在第三部分应用中介绍组合模式在源码中的实际运用,最后总结该设计模式学习后的一些思考。

读者可以拉取完整代码到本地进行学习,实现代码均测试通过后上传到码云,本地源码下载。

一、引出问题

上篇文章中老王给小王买车以后,小王对老王感激涕零,看着老王凌乱的书房,小王提出要帮助老王整理整理他的书架。

小王开始了他的分析。老王平时博览群书,中文、英文、梵文...每个语种占满了书架,而每个语种中又分经济学、计算机学、社会学等等类目。这是典型的分层次结构,将语种比作是图书的子类,类目是语种的子类结构划分。

将图书、语种、类目都看做是组织结构,他们之间没有继承关系,而是一个树形结构,可以更好的实现管理操作。

二、概念与使用

实际上,小王提出来的设计思路正是结构型设计模式中的组合模式,我们首先看一下组合模式的相关概念,组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以表示“整体-部分”的层次关系。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。

组合模式使得用户对单个对象和组合对象的访问具有一致性,即:组合能让客户以一致的方式处理个别对象以及组合对象。

用大白话解释也就是,在实际应用中将所有图书依照树形模式进行组合,老王寻找书籍时,无论是访问某一类书还是某一个语种的书,使用同样的姿势即可,保证了访问的一致性。

在该模式中应该是有三个角色:

1、Root :这是组合中对象声明接口,在适当情况下,实现所有类共有的接口默认行为,用于访问和管理Root 子部件, Root 可以是抽象类或者接口。

2、Branches:非叶子节点用于存储子部件,在Root接口中实现了 子部件的相关操作。

2、Leaf : 在组合中表示叶子节点,叶子节点没有子节点。

小王分析的头头是道,老王提出来了他的疑问。

当我按语种查找还是按类目查找是使用的方法有时候是不一样的,如果你把所有方法都定义在Root中,在语种或者类目中实现中是无意义的,而且这违背了接口隔离原则。

小王觉得说的对也不对,如果我改成不在Root中定义,那么我在客户端调用的时候就需要判断是枝还是叶了,增加了繁杂的逻辑判断,而且相比另外一种变得不透明了,依赖倒置原则也没有遵守。

两种方式似乎都有缺陷,小王陷入了纠结不知道该如何取舍,老王提出了他的一些见解,没有任何一个设计模式是完全没有缺点的,两种都有各自的好处,在实际的运用中根据条件进行取舍,而正确选择的前提就是要对所有的设计模式充分的把握。

上面两种就对应组合模式中的两个大分类、①透明组合模式、安全组合模式。

①透明组合模式把所有的公共方法都定义在Root中,这样做的好处就是客户端无需分辨是叶子节点(Leaf)和树枝节点(Branches),他们具备完全一致的接口;缺点是叶子节点(Leaf)会继承得到一些它所不需要(管理子类操作的方法)的方法,这与设计模式接口隔离原则相违背。

②安全组合模式的好处是接口定义职责清晰,符合设计模式单一职责原则和接口隔离原则;缺点是客户需要区分树枝节点(Branches)和叶子节点(Leaf),这样才能正确处理各个层次的操作,客户端依赖抽象(Root),违背了依赖倒置原则。

我们把两种的方式实现,读者对比他们之间的区别。

安全模式

Root(根节点):


public abstract class RootBook {
    protected String name;

    public RootBook(String name) {
        this.name = name;
    }

    public abstract String operation();

}

Branches(树枝节点)


public class BranchesLanguages extends RootBook {

    private List<RootBook> roots;

    public BranchesLanguages(String name) {
        super(name);
        this.roots = new ArrayList<RootBook>();
    }


    public String operation() {
        StringBuilder builder = new StringBuilder(this.name);
        for (RootBook component : this.roots) {
            builder.append("\n");
            builder.append(component.operation());
        }
        return builder.toString();

    }
    public boolean addChild(RootBook component) {
        return this.roots.add(component);
    }


    public boolean removeChild(RootBook component) {
        return this.roots.remove(component);
    }


    public RootBook getChild(int index) {
        return this.roots.get(index);
    }

}

Leaf(叶子节点)


public class LeafClassify extends RootBook {

    public LeafClassify(String name) {
        super(name);
    }

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

客户端:


public class Client {

    public static void main(String[] args) {
        System.out.println("安全组合模式...");
        // 来一个根节点
        BranchesLanguages BranchesRoot = new BranchesLanguages("root/书");
        // 来一个树枝节点
        BranchesLanguages branchA = new BranchesLanguages("------branchA/英语");
        BranchesLanguages branchB = new BranchesLanguages("------branchB/中文");
        // 来一个叶子节点
        RootBook leafA = new LeafClassify("------leafA/经济学");
        RootBook leafB = new LeafClassify("------leafB/计算机学");
        RootBook leafC = new LeafClassify("------leafC/法学");

        BranchesRoot.addChild(branchA);
        BranchesRoot.addChild(leafC);
        branchA.addChild(leafA);
        branchA.addChild(branchB);
        branchB.addChild(leafB);

        String result = BranchesRoot.operation();
        System.out.println(result);


    }
}

透明模式

Root(根节点):


public abstract class RootBook {
    protected String name;

    public RootBook(String name) {
        this.name = name;
    }

    public abstract String operation();

    public boolean addChild(RootBook component) {
        throw new UnsupportedOperationException("addChild not supported!");
    }

    public boolean removeChild(RootBook component) {
        throw new UnsupportedOperationException("removeChild not supported!");
    }

    public RootBook getChild(int index) {
        throw new UnsupportedOperationException("getChild not supported!");
    }

}

Branches(树枝节点)


public class BranchesLanguages extends RootBook {

    private List<RootBook> roots;

    public BranchesLanguages(String name) {
        super(name);
        this.roots = new ArrayList<RootBook>();
    }


    public String operation() {
        StringBuilder builder = new StringBuilder(this.name);
        for (RootBook component : this.roots) {
            builder.append("\n");
            builder.append(component.operation());
        }
        return builder.toString();

    }

    @Override
    public boolean addChild(RootBook component) {
        return this.roots.add(component);
    }


    @Override
    public boolean removeChild(RootBook component) {
        return this.roots.remove(component);
    }


    @Override
    public RootBook getChild(int index) {
        return this.roots.get(index);
    }

}

Leaf(叶子节点)


public class LeafClassify extends RootBook {

    public LeafClassify(String name) {
        super(name);
    }

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

客户端:


public class Client {

    public static void main(String[] args) {

        System.out.println("透明组合模式...");
        // 来一个根节点
        RootBook BranchesRoot = new BranchesLanguages("root/书");
        // 来一个树枝节点
        RootBook branchA = new BranchesLanguages("------branchA/英语");
        RootBook branchB = new BranchesLanguages("------branchB/汉语");
        // 来一个叶子节点
        RootBook leafA = new LeafClassify("------leafA/计算机学");
        RootBook leafB = new LeafClassify("------leafB/法学");
        RootBook leafC = new LeafClassify("------leafC/社会学");

        BranchesRoot.addChild(branchA);
        BranchesRoot.addChild(leafC);
        branchA.addChild(leafA);
        branchA.addChild(branchB);
        branchB.addChild(leafB);

        String result = BranchesRoot.operation();
        System.out.println(result);


    }
}

使用组合模式的两种实现方法,这样就对老王的书架改造工程就完成了,对凭空捏造出来的需求有些读者看完想必还是云里雾里。我们结合jdk的源码和一些开发常用框架,再次深入源码对组合模式的使用。

三、应用

通过查询资料可知,组合模式在Jdk中的应用主要是集合HashMap和Mybtis中的sqlnode

我们分别看其实现。

1、jdk中HashMap的运用

在HashMap中有一个父类AbstractMap和一个子类Node。如下图

我们看下源代码:

 public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable {
    ...
     public void putAll(Map<? extends K, ? extends V> m) {
        putMapEntries(m, true);
    }
    ...
    final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            }
            else if (s > threshold)
                resize();
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.geTKEy();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }
    ...
}

putAll()方法传入的是Map对象,Map就是一个抽象构件(同时这个构件中只支持健值对的存储格式),而HashMap是一个中间构件,HashMap中的Node节点就是叶子节点。

Node是HashMap中的一个内部类,HashMap的存储节点指的正是Node,读者可以重点看这个类的实现。

在这个实例中,HashMap就是树枝节点,Node就是叶节点,Map就是根节点。

2、Mybtis中的SqlNode

SqlNode是一个接口,主要功能就是构造SQL语句。

public interface SqlNode {
  boolean apply(DynamicContext context);
}

SqlNode有一大堆的实现类,我们看其中的MixedSqlNode。

  public class MixedSqlNode implements SqlNode {
  private final List<SqlNode> contents;

  public MixedSqlNode(List<SqlNode> contents) {
    this.contents = contents;
  }

  @Override
  public boolean apply(DynamicContext context) {
    contents.forEach(node -> node.apply(context));
    return true;
  }
}

SqlNode就充当组合模式中的Root,而他的众多子类作用就在于拼接各种类型的SQL,在组合模式的角色中相当于树枝节点。其中在TrimSqlNode 中有一个子类WhereSqlNode就充当组合模式中的树叶节点。

这两个都属于组合模式中的典型例子,读者体会下使用这种模式的好处,和如果不使用组合模式应该怎样实现。

通过这两个例子我们应该可以看到,设计模式的使用中并不是完全遵循各自的角色,更多的是设计模式中的一些变种,读者不深入源码并不能了解到该模式的实现细节。读者需要做的就是尽可能的熟悉设计模式,在自己开发过程中可以“择优录取”。

四、总结

到这里组合模式也就介绍完了,这种模式的优缺点都非常的明显,优点就在于清楚的定义分层次的结构,在调用时忽略他们之间的差异,方便对整个层次进行控制,但是组合模式会违反依赖倒置原则。

理解是一回事,在实际应用中能正确的使用它就是另外一回事了。

读者要对每种设计模式都能做到心中有数,当我们在实际编程中,在潜意识里有各个设计模式的大体轮廓,参考代入进各种设计模式中,对于简化开发和易于维护性有没有好的帮助,选择一个最优的设计模式。

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对编程网的支持。如果你想了解更多相关内容请查看下面相关链接

--结束END--

本文标题: Java设计模式之组合模式

本文链接: https://www.lsjlt.com/news/168559.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java设计模式之组合模式
    本文通过老王和小王探讨书房、书架、各类书的管理问题,引出结构型设计模式家族中的一个重要成员——组合模式,本文会给予两种组合模式的典型代码实现,为了加深理解会在...
    99+
    2022-11-13
  • 分析Java设计模式之组合模式
    目录一、概述二、 模式定义三、 模式结构四、 模式实现五、 模式优缺点5.1、优点5.2、缺点六、 模式适用场景七、 模式总结一、概述 我们对于这个图片肯定会非常熟悉,这两幅图片我...
    99+
    2022-11-12
  • Java设计模式之java组合模式详解
    目录引言组合模式介绍角色模式结构示例代码水果盘文件浏览更复杂的组合模式透明与安全透明组合模式安全组合模式组合模式总结优点缺点适用场景应用XML文档解析文件HashMapMybatis...
    99+
    2022-11-12
  • Java设计模式:组合模式
    目录概述结构组合模式案例分析总结在本讲,我们来学习一下结构型模式里面的第六个设计模式,即组合模式。 概述 在学习组合模式之前,我们先来看下面这张图。 对于以上这张图大家应该很熟悉,...
    99+
    2022-11-12
  • Java设计模式之组合模式深入刨析
    目录1.基本介绍2.结构3.组合模式解决的问题4.组合模式解决学校院系展示5.组合模式的注意事项和细节1.基本介绍 1)组合模式(Composite Pattern),又叫部分整体模...
    99+
    2022-11-13
  • 深入理解Java设计模式之组合模式
    目录一、什么是组合模式动机(Motivation)意图(Intent)二、组合模式的结构结构图说明:三、组合模式的使用场景四、组合模式的优缺点五、组合模式的实现六、组合模式的.NET...
    99+
    2022-11-12
  • Java设计模式之组合模式实例分析
    这篇文章主要介绍“Java设计模式之组合模式实例分析”,在日常操作中,相信很多人在Java设计模式之组合模式实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java设计模式之组合模式实例分析”的疑惑有所...
    99+
    2023-06-30
  • Java设计模式之组合模式的示例详解
    目录定义原理类图案例需求方案分析总结定义 组合模式,又叫部分整体模式,它创建了对象组的数据结构(将对象组合成树状结构,用来表示部分整体的层级关系)组合模式使得用户对单个对象和组合对象...
    99+
    2022-11-13
  • Java结构型设计模式之组合模式详解
    目录组合模式应用场景优缺点主要角色组合模式结构分类透明组合模式创建抽象根节点创建树枝节点创建叶子节点客户端调用安全组合模式创建抽象根节点创建树枝节点创建叶子节点客户端调用组合模式 组...
    99+
    2022-11-13
  • Golang设计模式之组合模式讲解
    目录组合模式概念示例组合模式 组合是一种结构型设计模式, 你可以使用它将对象组合成树状结构, 并且能像使用独立对象一样使用它们。 对于绝大多数需要生成树状结构的问题来说, 组合都是非...
    99+
    2023-01-14
    Go组合模式 Go组合模式
  • Android设计模式系列之组合模式
    Android中对组合模式的应用,可谓是泛滥成粥,随处可见,那就是View和ViewGroup类的使用。在android UI设计,几乎所有的widget和布局类都依靠这两个类...
    99+
    2022-06-06
    组合模式 Android
  • java设计模式-组合模式详解
    目录组合模式Demo代码:总结组合模式 组合模式(Composite Pattern)又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来...
    99+
    2022-11-12
  • Java设计模式中的组合模式
    目录模式介绍UML类图组合模式案例组合模式的注意事项和细节模式介绍 组合模式(Composite Pattern),又叫部分整体模式,它创建了对象组的树形结构,将对象组合成树状结构以...
    99+
    2022-11-13
  • Java结构型设计模式之组合模式CompositePattern详解
    目录概述三大组件应用案例顶层组件OrganizationComponentComposite组件叶子节点客户端测试UML类图总结概述 组合模式(Composite Pattern),...
    99+
    2022-11-13
    Java Composite Pattern Java 组合模式
  • 每天一个设计模式之组合模式
    作者按:《每天一个设计模式》旨在初步领会设计模式的精髓,目前采用javascript和python两种语言实现。诚然,每种设计模式都有多种实现方式,但此小册只记录最直截了当的实现方式 :) 原文地址是:《每天一个设计模式之组合模式》 欢迎...
    99+
    2023-01-31
    模式 组合
  • .Net结构型设计模式之组合模式(Composite)
    目录一、动机(Motivate)二、意图(Intent)三、结构图(Structure)四、模式的组成五、组合模式的具体代码实现1、透明式的组合模式2、安全式的组合模式六、组合模式的...
    99+
    2022-11-13
  • JavaScript设计模式组合设计模式案例
    目录前言组合设计模式的业务场景组合设计模式小案例前言 组合设计模式是用于将多个部分通过组合的方式行成一个整体,就比如我们去吃饭,点了一份米饭和一份鱼香肉丝,这些东西可以看成一个部分,...
    99+
    2022-11-13
  • 如何理解Java设计模式的组合模式
    这篇文章主要介绍“如何理解Java设计模式的组合模式”,在日常操作中,相信很多人在如何理解Java设计模式的组合模式问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解Java设计模式的组合模式”的疑惑有所...
    99+
    2023-06-25
  • Java设计模式之单例模式
    目录什么是设计模式?单例模式是什么?单例模式设计的原则是什么?Java实现单例模式的5种方式?懒汉饿汉静态内部类双重校验锁DCL(Double Check Lock)枚举(num)总...
    99+
    2022-11-12
  • Java设计模式之桥接模式
    本文通过老王和小王买车,引出设计模式中的结构型设计之桥接模式,接着说明设计型模式的概念和代码实现,为了加深理解,会说明适配器设计模式在JDBC中的应用,最后谈谈桥接模式和适配器模式的...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作