(十)Head first design patterns组合模式(c++)

news2024/9/24 23:30:26

组合模式

组合模式在参考链接中已经讲得很好了,这里只简单讲讲就好。

组合模式的意图是表达部分-整体层次结构。

当你需要管理一个组合对象,又要管理这个组合对象的单个对象。这个时候就可以让这个组合对象和单个对象继承同一个基类,以便用基类指针做统一管理。

当基类指针去调用operation方法时,如果这个这个指针指向的是Composite对象,则调用的是Composite对象的operation方法,这个方法中的for循环会挨个遍历各个vector中的指针,如果遍历的指针指向的还是Composite对象,则继续调用Composite对象的operation方法。如果指针指向的单元是Leaf对象,则会调用Leaf对象中的operation方法。

如果不是写成组合模式,一般常用的递归函数会怎么写?首先也是遍历父节点,如果父节点有子节点就去遍历子节点,直到遍历完叶子节点。组合模式比较巧妙的是,在编译的时候,虚函数operation已经根据指针是指向基类还是子类分好了,所以递归函数中省去了判断是否是叶子节点的过程,而是让指针自行去判断。(设计模式经常干的一件事就是:把需用判断的地方巧妙的用继承虚函数来实现)

组合模式+迭代器模式

怎么用迭代器的方式去迭代Composite对象呢?

可以相应写一个CompositeIterator对象。迭代器其实有点像一个托管,对象将自己的链接地址给到迭代器,由迭代器的hasNext判断后面还有没数据,由next返回下一个容器对象。

关键代码

next(): 返回下一个对象,同时把composite对象创建的迭代器加入到iterators容器中。

hasNext(): 判断是否可迭代,如果不可迭代则继续删除此迭代器,继续寻找到下一个可迭代的迭代器。找到则返回true。

template<class T>
class CompositeIterator : public Iterator<T>{
public:
    CompositeIterator(Iterator<T>* iterator){ iterators.push_back(iterator); }
    T next(){
        Iterator<T>* iterator = iterators[0];
        T item = iterator->next();
        iterator = item->createIterator();
        if(iterator->hasNext()){ // 这里leaf的迭代器hasNext返回的是false,故而不会添加进去
            iterators.push_back(iterator);
        } 
        return item;
    }
    bool hasNext(){
        if(iterators.size()==0) return false;
        Iterator<T>* iterator = iterators[0];
        if(!iterator->hasNext()){ 
            iterators.erase(iterators.begin()); // 已经没法迭代了,继续下一个迭代对象
            return hasNext();
        } else {
            return true;
        }
    }
private:
    vector<Iterator<T>*> iterators;
};

统一vsctor接口代码

这里为了让vector的迭代器也有hasNext()和next()接口,重写了一个newVector对象,其行为类似vector。

template<class T>
class Iterator{
public:
    virtual bool hasNext(){}
    virtual T next(){}
    virtual bool isComposite(){}
};
template<class T>
class newVectorIterator : public Iterator<T>{
public:
    newVectorIterator(vector<T> *p):p(p){}
    T next(){
        T t = p->at(position);
        position++;
        return t;
    }
    bool hasNext(){
        if(position >= p->size()) 
            return false;
        else
            return true;
    }
    vector<T> *p;
    int position = 0;
};
template<class T>
class newVector{
public:
    void push_back(T item){
        mVector.push_back(item);
    }
    T operator[](int index){
        return mVector[index];
    }
    int size(){
        return mVector.size();
    }
    Iterator<T>* createIterator(){
        return new newVectorIterator<T>(&mVector);
    }
    vector<T> mVector;
};

全部代码

#include<iostream>
#include<string>
#include<vector>
using namespace std;

template<class T>
class Iterator{
public:
    virtual bool hasNext(){}
    virtual T next(){}
    virtual bool isComposite(){}
};
template<class T>
class newVectorIterator : public Iterator<T>{
public:
    newVectorIterator(vector<T> *p):p(p){}
    T next(){
        T t = p->at(position);
        position++;
        return t;
    }
    bool hasNext(){
        if(position >= p->size()) 
            return false;
        else
            return true;
    }
    vector<T> *p;
    int position = 0;
};
template<class T>
class newVector{
public:
    void push_back(T item){
        mVector.push_back(item);
    }
    T operator[](int index){
        return mVector[index];
    }
    int size(){
        return mVector.size();
    }
    Iterator<T>* createIterator(){
        return new newVectorIterator<T>(&mVector);
    }
    vector<T> mVector;
};

template<class T>
class NullIterator : public Iterator<T>{
public:
    T next(){ return nullptr; }
    bool hasNext(){ return false; }
};
template<class T>
class CompositeIterator : public Iterator<T>{
public:
    CompositeIterator(Iterator<T>* iterator){ iterators.push_back(iterator); }
    T next(){
        Iterator<T>* iterator = iterators[0];
        T item = iterator->next();
        iterator = item->createIterator();
        if(iterator->hasNext()){
            iterators.push_back(iterator);
        } 
        return item;
    }
    bool hasNext(){
        if(iterators.size()==0) return false;
        Iterator<T>* iterator = iterators[0];
        if(!iterator->hasNext()){
            iterators.erase(iterators.begin());
            return hasNext();
        } else {
            return true;
        }
    }
private:
    vector<Iterator<T>*> iterators;
};
class Compoment{
public:
    virtual ~Compoment(){ std::cout << "~Compoment()" << endl; }
    virtual void operation() = 0;
    virtual void operation1() = 0;
    virtual void add(Compoment *com){}
    virtual void remove(Compoment *com){}
    virtual Compoment* findChild(int index){ return nullptr; }
    virtual Iterator<Compoment*>* createIterator(){}
};
class Leaf : public Compoment{
public:
    Leaf(int num) : num(num) {}
    ~Leaf(){ std::cout << "~Leaf()" << num << endl;}
    virtual void operation() { cout << "Leaf::operation()" << num << endl; }
    void operation1(){ std::cout << "Leaf::operation1()" << num << std::endl; }
    Iterator<Compoment*>* createIterator(){
        return new NullIterator<Compoment*>();
    }
private:
    int num;
};
class Composite : public Compoment{
public:
    Composite(){}
    ~Composite(){
        std::cout << "~Composite()" << std::endl;
    }
    void operation(){
        std::cout << "Composite::operation()" << std::endl;
        for(int i = 0; i < coms.size(); i ++ ){
            coms[i]->operation();
        }
    }
    void operation1(){
        std::cout << "Composite::operation1()" << std::endl;
    }
    bool isComposite(){ return true; }
    void add(Compoment *com){ coms.push_back(com); }
    Compoment* findChild(int index){
        if(index < 0 || index >= coms.size()){
            return nullptr;
        }
        return coms[index];
    }
    Iterator<Compoment*>* createIterator(){
        return new CompositeIterator<Compoment*>(coms.createIterator());
    }
private:
    newVector<Compoment*> coms;
};

void doCompositePattern(){
    std::cout << "-----------com1->operation()-----------" << std::endl;
    Compoment *com1 = new Composite();
    com1->add(new Leaf(1));
    com1->add(new Leaf(2));
    com1->add(new Leaf(3));
    com1->operation();
    std::cout << "-----------com2->operation()-----------" << std::endl;
    Compoment *com2 = new Composite();
    com2->add(new Leaf(4));
    com2->add(com1);
    com2->add(com1);
    com1->add(new Leaf(11));
    com2->operation();

    std::cout << "\n-----------iterator-----------" << std::endl;
    Iterator<Compoment*>* iterator = com2->createIterator();
    while(iterator->hasNext()){
        iterator->next()->operation1();
    }
}

int main(){
    doCompositePattern();
    return 0;
}

 参考

​​​​​​​​​​​​​​C++设计模式——组合模式(composite pattern)_c++ 设计模式组合-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1403862.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android14实战:调整A2DP音量曲线(五十三)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

【YOLO系列】 YOLOv4之SAT自对抗训练

一、简介 自对抗训练&#xff08;Self-Adversarial Training&#xff0c;简称SAT&#xff09;是一种新型的数据增强技术&#xff0c;旨在通过神经网络自身进行的对抗式攻击来提高模型的鲁棒性和泛化能力。其主要分为两个阶段&#xff1a; 第一阶段&#xff0c;神经网络会对其原…

C# wpf利用Clip属性实现截屏框

wpf截屏系列 第一章 使用GDI实现截屏 第二章 制作截屏框&#xff08;本章&#xff09; ______第一节 使用DockPanel制作截屏框 ______第二节 利用Clip属性实现截屏框(本节) 第三章 实现截屏框热键截屏 第四章 实现截屏框实时截屏 第五章 使用ffmpeg命令行实现录屏 文章目录 wp…

JVM系列-1.初识JVM

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

Netty篇章(1)—— 核心原理介绍

终于进入到Netty框架的环节了&#xff0c;前面介绍了大量的Java-NIO的内容&#xff0c;核心的内容Selector、Channel、Buffer、Reactor掌握了&#xff0c;那么学起来Netty也是水到渠成的事情。如果没有掌握前面的内容那么学Netty会非常吃力&#xff0c;下面讲解Netty核心原理与…

界面控件DevExpress ASP.NET Data Grid组件 - 可快速处理各类型数据!(一)

由DevExpress开发的快速且功能完整的ASP.NET Web Forms的Data Grid组件&#xff0c;从全面的数据塑造和数据过滤选项到十多个集成数据编辑器&#xff0c;该套件提供了帮助用户构建极佳数据所需的一些&#xff0c;没有限制&#xff01; P.S&#xff1a;DevExpress ASP.NET Web …

探索设计模式的魅力:一次设计,多次利用,深入理解原型模式的设计艺术

原型模式是一种设计模式&#xff0c;属于创建型模式的一种&#xff0c;它用于创建重复的对象&#xff0c;同时又能保持性能。在原型模式中&#xff0c;通过复制现有对象的原型来创建新对象&#xff0c;而不是通过实例化类来创建对象。这样做可以避免耗费过多的资源开销&#xf…

关于缓存 db redis local 取舍之道

文章目录 前言一、影响因素二、db or redis or local1.db2.redis3. local 三、redisson 和 CaffeineCache 封装3.1 redisson3.1.1 maven3.1.2 封装3.1.3 使用 3.2 CaffeineCache3.1.1 maven3.1.2 封装3.1.3 使用 总结 前言 让我们来聊一下数据缓存&#xff0c;它是如何为我们带…

01 Redis的特性

1.1 NoSQL NoSQL&#xff08;“non-relational”&#xff0c; “Not Only SQL”&#xff09;&#xff0c;泛指非关系型的数据库。 键值存储数据库 &#xff1a; 就像 Map 一样的 key-value 对。如Redis文档数据库 &#xff1a; NoSQL 与关系型数据的结合&#xff0c;最像关系…

Linux的一些快捷键(hot keyboard)

Ctrl Alt t&#xff1a;打开bash&#xff08;就是命令框窗口&#xff09; Ctrl Alt F3~F6&#xff1a;打开tty终端&#xff08;纯命令行终端&#xff0c;每个Linux发行版不相同&#xff0c;我的是Ubuntu20版&#xff09; Alt F4&#xff1a;关闭当前窗口&#xff08;Windo…

扫地机器人(二分算法+贪心算法)

1. if(robot[i]-len<sweep)这个代码的意思是——如果机器人向左移动len个长度后&#xff0c;比现在sweep的位置&#xff08;现在已经覆盖的范围&#xff09;还要靠左&#xff0c;就是覆盖连续不起来&#xff0c;呢么这个len就是有问题的&#xff0c;退出函数&#xff0c;再…

HTTP 基本概念

1. HTTP &#xff08;Hypertext Transfer Protocol&#xff09;超文本传输协议&#xff0c;是互联网上应用最为广泛的协议之一。 小林coding的解析特别通俗易懂 https://xiaolincoding.com/network/2_http/http_interview.html#http-%E6%98%AF%E4%BB%80%E4%B9%88 协议&#…

elementPlust 的el-select在提示框关闭时自动弹出

问题&#xff1a; 当el-select添加filterable属性时&#xff0c;弹提示窗时&#xff0c;点击确定后&#xff0c;下拉框会自动弹出 分析&#xff1a; 主要问题就是因为filterable属性&#xff0c;根本解决方案是选中的时候让他失去焦点 el-select有一个visible-change事件&…

本地生活服务平台加盟,成功路上的注意事项

近年来&#xff0c;随着短视频的快速发展&#xff0c;本地生活服务成为了一个蓬勃发展的行业。作为创业者&#xff0c;加盟本地生活服务平台是一个有潜力的商机。然而&#xff0c;在决定加入并投资之前&#xff0c;有一些关键的注意事项需要考虑。 选择一个信誉良好、口碑较好的…

【PWN · 格式化字符串|劫持fini_array|劫持got表】[CISCN 2019西南]PWN1

格式化字符串的经典利用&#xff1a;劫持got表。但是遇到漏洞点只能执行一次的情况&#xff0c;该怎么办&#xff1f; 前言 如果存在格式化字符串&#xff0c;保护机制开的不健全&#xff0c;通常可以劫持got表&#xff0c;构造后门函数。然而&#xff0c;如果不存在循环、栈溢…

手机流量卡信号弱强好坏是哪些因素来决定的呢?

大家好&#xff0c;我是平台小编&#xff0c;现在是不是还有很多人一直认为这个手机信号是跟这个卡是有直接关系的&#xff0c;信号不好的时候&#xff0c;就是手机卡的问题呢&#xff1f;下面我就给大家普及一下这个常识&#xff0c;希望能对大家有帮助&#xff01; 大家千万不…

CentOS配置阿里云yum源和阿里云epel源

CentOS配置阿里云yum源和阿里云epel源 前言&#xff1a;一、 备份二、 配置阿里云yum源三、 配置阿里云epel源四、测试 前言&#xff1a; 阿里云地址 https://developer.aliyun.com/mirror/一、 备份 cd /etc/yum.repos.d/ && mkdir bak mv *.repo *repo.rpmnew ./b…

从编程中思考:大脑的局部与全局模式(一)

郭靖正在帐篷中用Unity写代码&#xff0c;刚写完一段代码。欧阳锋从帐篷外走进来&#xff0c;正要说点什么&#xff0c;郭靖反应敏捷&#xff0c;转身反手一招神龙摆尾击出&#xff0c;将欧阳锋震出帐篷&#xff0c;灰溜溜逃跑。 using UnityEngine;public class LocalGlobalD…

[MySQL]关于表的增删改查

目录 1.插入 1.1单行数据全列插入 1.2多行插入&#xff0c;指定列插入 ​编辑2.查询 2.1全列查询 2.2指定列查询 3.3查询字段为表达式 2.4别名 ​编辑2.5去重 2.6排序 2.7条件查询 2.7.1基本查询: 2.7.2 AND 和OR 2.7.3范围查询 2.7.4模糊查询 2.7.5分页查询 limit …

竞赛保研 机器视觉目标检测 - opencv 深度学习

文章目录 0 前言2 目标检测概念3 目标分类、定位、检测示例4 传统目标检测5 两类目标检测算法5.1 相关研究5.1.1 选择性搜索5.1.2 OverFeat 5.2 基于区域提名的方法5.2.1 R-CNN5.2.2 SPP-net5.2.3 Fast R-CNN 5.3 端到端的方法YOLOSSD 6 人体检测结果7 最后 0 前言 &#x1f5…