C++【组合模式】

这篇具有很好参考价值的文章主要介绍了C++【组合模式】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简单介绍

组合模式是一种结构型设计模式, 只有在可以将对象拆分为【树状结构】的情况下使用。并且像使用独立对象一样使用它们。
常用于表示与图形打交道的用户界面组件或代码的层次结构。

基础理解

C++【组合模式】,动态规划题目集,c++,组合模式,docker,设计模式

Q:为什么要用组合模式 ?
A:在一个树状的结构中,叶子节点与父节点的距离会很远,使用循环语句一个一个遍历会大大增加复杂度。所以需要使用一个通用接口将叶子节点与父节点实现交互。

Q:如何设计组合模式 ?
A:对于一个字节点,直接返回你需要的东西,对于父节点,则会遍历其所有的子节点,最后 " 汇总 " 结果给其父节点
C++【组合模式】,动态规划题目集,c++,组合模式,docker,设计模式


优点:无需了解构成树状结构的对象的具体类,无论复杂简单。直接调用接口进行处理,对象会沿着树结构递归下去

识别方法: 组合模式会将同一抽象或接口类型的实例放入树状结构。

UML

C++【组合模式】,动态规划题目集,c++,组合模式,docker,设计模式

实现方式

  1. 首先确保你自己 的模型能被拆分为树状结构。并且尝试分解为简单元素和容器(必须能够同时包含简单元素和其他容器)
  2. 声明组件接口及其一系列方法, 这些方法对简单和复杂元素都有意义。
  3. 创建一个叶节点类表示简单元素。 程序中可以有多个不同的叶节点类。
  4. 创建一个容器类表示复杂元素,创建一个数组成员变量来存储对于其子元素的引用。需要能同时保存叶节点和容器(父类)
  5. 在容器中定义添加和删除子元素的方法。

#include <algorithm>
#include <iostream>
#include <list>
#include <string>

/**
 * 基础组件类声明了复合对象和简单对象的共同操作。
 */
class Component
{
    /**
     * @var Component
     */
protected:
    Component *parent_;
    /**
     * 可选地,基础组件可以声明一个接口,用于设置和访问组件在树结构中的父级。它还可以为这些方法提供一些默认实现。
     */
public:
    virtual ~Component() {}
    void SetParent(Component *parent)
    {
        this->parent_ = parent;
    }
    Component *GetParent() const
    {
        return this->parent_;
    }
    /**
     * 在某些情况下,在基础组件类中定义管理子组件的操作会很有益。这样,即使在对象树组装期间,您也不需要向客户端代码公开任何具体的组件类。缺点是对于叶级组件,这些方法将为空。
     */
    virtual void Add(Component *component) {}
    virtual void Remove(Component *component) {}
    /**
     * 您可以提供一个方法,让客户端代码确定组件是否可以拥有子组件。
     */
    virtual bool IsComposite() const
    {
        return false;
    }
    /**
     * 基础组件可以实现一些默认行为,或者将其委托给具体类(通过将包含行为的方法声明为“abstract”)。
     */
    virtual std::string Operation() const = 0;
};

/**
 * 叶级类表示组合的末端对象。叶级对象不能有任何子节点。
 *
 * 通常情况下,真正的工作是由叶级对象完成的,而复合对象只是将任务委派给它们的子组件。
 */
class Leaf : public Component
{
public:
    std::string Operation() const override
    {
        return "Leaf";
    }
};

/**
 * Composite 类代表可能具有子组件的复杂组件。
 * 通常,Composite 对象将实际工作委托给它们的子组件,
 * 然后“汇总”结果。
 */
class Composite : public Component
{
protected:
    std::list<Component *> children_;

public:
    /**
     * Composite 对象可以向其子组件列表中添加或删除其他组件(简单或复杂)。
     */
    void Add(Component *component) override
    {
        this->children_.push_back(component);
        component->SetParent(this);
    }

    /**
     * 注意,此方法只是从列表中移除指针,但不释放内存,
     * 您应该手动释放内存,或者最好使用智能指针。      
     * 我使用手动,简单理解
     */
    void Remove(Component *component) override
    {
        children_.remove(component);
        component->SetParent(nullptr);
        delete component;
    }

    bool IsComposite() const override
    {
        return true;
    }

    /**
     * Composite 在特定方式下执行其主要逻辑。
     * 它递归遍历所有子组件,收集和汇总它们的结果。
     * 由于 Composite 的子组件会将这些调用传递给它们的子组件,以此类推,
     * 整个对象树将被遍历并返回结果。
     */
    std::string Operation() const override
    {
        std::string result;
        for (const Component *c : children_)
        {
            if (c == children_.back())
            {
                result += c->Operation();
            }
            else
            {
                result += c->Operation() + "+";
            }
        }
        return "Branch(" + result + ")";
    }
};

/**
 * 客户端代码通过基础接口与所有组件一起工作。
 */
void ClientCode(Component *component)
{
    // ...
    std::cout << "RESULT: " << component->Operation(); //同一接口
    // ...
}

/**
 * 由于子组件管理操作在基类 Component 中声明,
 * 客户端代码可以处理任何组件,无论是简单还是复杂,而不依赖于具体的类。
 */
void ClientCode2(Component *component1, Component *component2)
{
    // ...
    if (component1->IsComposite())
    {
        component1->Add(component2);
    }
    std::cout << "RESULT: " << component1->Operation();
    // ...
}

/**
 * 这样,客户端代码可以支持简单的叶子组件...
 */

int main()
{
    Leaf *leaf = new Leaf;
    std::cout << "Client: 我有一个简单的组件:\n";
    ClientCode(leaf);
    std::cout << "\n\n";

    /**
     * ...以及复杂的 Composite 组件。
     */
    Composite *tree = new Composite;
    Composite *branch1 = new Composite;
    Composite *branch2 = new Composite;
    Leaf *leaf1 = new Leaf;
    Leaf *leaf2 = new Leaf;
    Leaf *leaf3 = new Leaf;
    Leaf *leaf4 = new Leaf;

    branch1->Add(leaf1);
    branch1->Add(leaf2);
    branch2->Add(leaf3);
    branch2->Add(leaf4);
    tree->Add(branch1);
    tree->Add(branch2);
    std::cout << "Client: 现在我有一个复合树结构:\n";
    ClientCode(tree);
    std::cout << "\n\n";

    std::cout << "Client: 即使在管理树结构时,我不需要检查组件的具体类:\n";
    ClientCode2(tree, leaf);
    std::cout << "\n";

    delete leaf;
    delete tree;
    delete branch1;
    delete branch2;
    delete leaf1;
    delete leaf2;
    delete leaf3;
    delete leaf4;
    system("pause");
    return 0;
}

应用场景

  1. 实现树状对象结构, 可以使用组合模式。

大致可以理解为,两种共享公共接口的基本元素: 简单叶节点和复杂容器(包含其他容器)

  1. 客户端代码以相同方式处理简单和复杂元素

同一接口就是相同方式,但可以使用组合模式同时处理简单和复杂元素。

与其他模式的关系

  1. 桥接模式、 状态模式和策略模式 (在某种程度上包括适配器模式:将转换接口的工作给适配器) 模式的接口非常相似。 实际上, 它们都基于组合模式——即将工作委派给其他对象, 不过也各自解决了不同的问题。
    (模式并不只是以特定方式组织代码的配方, 你还可以使用它们来和其他开发者讨论模式所解决的问题。)

  2. 你可以在创建复杂组合树时使用生成器模式, 因为这可使其构造步骤以递归的方式(特定的方式)运行。

  3. 责任链模式通常和组合模式结合使用。 在这种情况下, 叶组件接收到请求后, 可以将请求沿包含全体父组件的链一直传递至对象树的底部。

  4. 你可以使用 迭代器模式 来遍历组合树。
    (对不同结构使用不同的迭代方式,有点类似策略模式:使用对应的算法解决问题)

  5. 你可以使用访问者模式对整个组合树执行操作。

  6. 你可以使用享元模式实现组合树的共享叶节点以节省内存。

  7. 组合和装饰模式的结构图很相似, 因为两者都依赖递归组合来组织无限数量的对象。文章来源地址https://www.toymoban.com/news/detail-847888.html

    • 装饰类似于组合,对一个产品套上一层层装饰,最终的结构十分相似。 但其只有一个子组件。 此外还有一个明显不同: 装饰为被封装对象添加了额外的职责, 组合仅对其子节点的结果进行了 “求和”。
    • 模式也可以相互合作: 你可以使用装饰来扩展组合树中特定对象的行为。
    • 大量使用组合和装饰的设计通常可从对于原型模式的使用中获益。 你可以通过该模式来复制复杂结构, 而非从零开始重新构造。

到了这里,关于C++【组合模式】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式——组合模式08

    组合模式:把类似对象或方法组合成结构为树状的设计思路。 例如部门之间的关系。 设计模式,一定要敲代码理解 满足开闭原则。叶子结点与非叶子结点都继承或实现同一抽象,只是叶子功能权限少,而非叶子结点需要容器记录子节点。 代码下载

    2024年04月11日
    浏览(37)
  • 设计模式:组合模式

    组合模式是一种结构型设计模式,用于将对象组织成树形结构,以表示“部分-整体”的层次结构。组合模式使得客户端可以统一地处理单个对象和组合对象,而不需要区分它们之间的差异。 在组合模式中,有两种主要类型的对象:叶节点和组合节点。叶节点表示树结构中的

    2024年02月07日
    浏览(47)
  • 【C++ 观察者模式 思想理解】C++中的观察者模式:松耦合设计与动态交互的艺术,合理使用智能指针观察者

    在进入技术细节之前,理解观察者模式(Observer Pattern)的基本概念和它在现代编程中的重要性是至关重要的。 观察者模式是一种设计模式,它定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。在C++中,这个

    2024年01月24日
    浏览(44)
  • 设计模式浅析(十) ·设计模式之迭代器&组合模式

    日常叨逼叨 java设计模式浅析,如果觉得对你有帮助,记得一键三连,谢谢各位观众老爷😁😁 案例 有两家门店,门店A呢只提供早餐,门店B呢只提供午餐,有一天这两家店铺想要进行合并,一起做大做强,再创辉煌。 合并后呢,对于菜单的定制存在了一定的问题: 门店A的

    2024年04月11日
    浏览(38)
  • 结构型设计模式之组合模式【设计模式系列】

    C++技能系列 Linux通信架构系列 C++高性能优化编程系列 深入理解软件架构设计系列 高级C++并发线程编程 设计模式系列 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the future of dream weaving wings, let the dream fly in reali

    2024年02月15日
    浏览(39)
  • 【二十】【动态规划】879. 盈利计划、377. 组合总和 Ⅳ、96. 不同的二叉搜索树 ,三道题目深度解析

    动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利用已经计算好的小问题的解,而不需要重

    2024年01月16日
    浏览(25)
  • 【23种设计模式】组合模式【⭐】

    个人主页 :金鳞踏雨 个人简介 :大家好,我是 金鳞 ,一个初出茅庐的Java小白 目前状况 :22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客 :这里是CSDN,是我学习技术,总结知识的地方。希望和各位大佬交流,共同进

    2024年02月09日
    浏览(34)
  • Java设计模式-组合模式

    在软件设计中,设计模式是一种被广泛接受和应用的经验总结,旨在解决常见问题并提供可复用的解决方案。 组合模式是一种结构型设计模式,它允许将对象组合成树形结构以表示“部分-整体”的层次结构。这种模式能够使客户端以一致的方式处理单个对象和对象集合,将

    2024年02月06日
    浏览(30)
  • 设计模式-组合模式(Composite)

    组合模式(Composite Pattern)是一种结构型设计模式,它允许你将对象组合成树状结构以表示“整体-部分”的层次结构。组合模式使得客户端可以统一处理单个对象和对象组合,而不需要区分它们。 在本篇博客中,我们将详细介绍组合模式的概念,并提供一个简单的Java代码示

    2024年02月09日
    浏览(38)
  • 设计模式之组合模式笔记

    记录下学习设计模式-组合模式的写法。JDK使用版本为1.8版本。 意图 :将对象组合成树型结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 结构 : 其中: Component为组合中的对象声明接口;在适当情况下实现所有类共有接口的默认

    2024年02月11日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包