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

组合模式

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

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

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

当基类指针去调用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.mfbz.cn/a/341291.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytorch学习笔记(十一)

优化器学习 把搭建好的模型拿来训练&#xff0c;得到最优的参数。 import torch.optim import torchvision from torch import nn from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear from torch.utils.data import DataLoaderdataset torchvision.datas…

E. Increasing Subsequences

Part1 寒假思维训练之每日一道构造题&#xff08;思维 构造 数学&#xff09;题目链接&#xff1a; Problem - E - Codeforces 题意&#xff1a; 给定一个整数&#xff0c;数字n的范围是&#xff0c;闭区间&#xff0c;要求构造一个递增子序列&#xff08;可以不连续&…

在Python环境中运行R语言的配环境实用教程

前情提要 在做一些生物信息与医学统计的工作&#xff0c;本来偷懒希望只靠python完成的&#xff0c;结果还是需要用R语言&#xff0c;倒腾了一会儿&#xff0c;调成功了&#xff0c;就记录一下这个过程。 我的环境&#xff1a; win10, pycharm, R-4.3.2 首先&#xff0c;我们…

proxy 代理的接口报错301问题

项目系统里仅仅这个接口报错&#xff0c;反向代理错误导致。 默认情况下&#xff0c;不接受运行在HTTPS上&#xff0c;且使用了无效证书的后端服务器。如果你想要接受&#xff0c;修改配置&#xff1a;secure: false&#xff08;简单意思&#xff1a;如果本地没有进行过https相…

Armv8-M的TrustZone技术之内存属性单元

如果处理器包含Armv8-M安全扩展&#xff0c;则内存区域的安全状态由内部安全属性单元&#xff08;SAU&#xff0c;Secure Attribution Unit&#xff09;或外部实现定义的属性单元&#xff08;IDAU&#xff0c;Implementation Defined Attribution Unit&#xff09;的组合控制。…

如何在 Ubuntu 22.04 上安装 Apache Web 服务器

前些天发现了一个人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;最重要的屌图甚多&#xff0c;忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Apache Web 服务器 介绍 Apache HTTP 服务器是世界上使用最广泛的 Web 服务器。它…

苹果眼镜(Vision Pro)的开发者指南(3)-【3D UI SwiftUI和RealityKit】介绍

为了更深入地理解SwiftUI和RealityKit,建议你参加专注于SwiftUI场景类型的系列会议。这些会议将帮助你掌握如何在窗口、卷和空间中构建出色的用户界面。同时,了解Model 3D API将为你提供更多关于如何为应用添加深度和维度的知识。此外,通过学习RealityView渲染3D内容,你将能…

8.前端--CSS-显示模式

元素的显示模式 元素显示模式就是元素&#xff08;标签&#xff09;以什么方式进行显示&#xff0c;比如<div>自己占一行&#xff0c;比如一行可以放多个<span>。 1.块元素 常见的块元素 常见的块元素&#xff1a;<h1>~<h6>、<p>、<div>、…

01 Redis的特性

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

大模型的学习路线图推荐—多维度深度分析【云驻共创】

&#x1f432;本文背景 近年来&#xff0c;随着深度学习技术的迅猛发展&#xff0c;大模型已经成为学术界和工业界的热门话题。大模型具有数亿到数十亿的参数&#xff0c;这使得它们在处理复杂任务时表现得更为出色&#xff0c;但同时也对计算资源和数据量提出了更高的要求。 …

二、arcgis 点shp数据处理

在工作中&#xff0c;很多时候客户会提供点坐标&#xff0c;那么要想把点坐标生成shp文件&#xff0c;有两种方法&#xff08;坐标系CGCS2000&#xff09;&#xff1a; 1.当只有个位数的点坐标时&#xff0c;可以直接在arcgisMap中添加&#xff0c;具体步骤如下&#xff1a; …

【JavaSE】第一个Java程序

前提引入 在JavaSE的系列中&#xff0c;将从第一个Java程序开始叙述&#xff0c;系统的把JavaSE的内容总结一次。毕竟这是第二次学习JavaSE的内容&#xff0c;因此感触也相对比较深一些。在JavaSE的初步计划中&#xff0c;大概有十一到十三篇文章&#xff0c;大致有&#xff1…

docker 安装手册

docker 安装手册 第一步卸载旧的docker (如果安装过Docker否则跳过此步) 以防万一最好执行一遍 yum -y remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 第二步&#xff0c;安装相关…

ROS第 11 课 参数的使用与编程方法

文章目录 第 11 课 参数的使用与编程方法1.服务模型2.rosparam参数2.1 rosparam详细参数2.2 运行海龟例程2.3 rosparam的使用 3.编程方法3.1 编写控制程序 4.运行程序 第 11 课 参数的使用与编程方法 1.服务模型 &emap;&emsp在ROS master当中有一个参数服务器&#x…

Linux系统Shell脚本 ----- 编程规范和变量详细解读(一)

一、程序编程风格 面向过程语言 开发的时候 需要 一步一步 执行 做一件事情&#xff0c;排出个步骤&#xff0c;第一步干什么&#xff0c;第二步干什么&#xff0c;如果出现情况A&#xff0c;做什么处理&#xff0c;如果出现了情况B&#xff0c;做什么处理 问题规模小&#…

imgaug库图像增强指南(35):【iaa.Fog】——轻松创建自然雾气场景

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

gin如何实现热更新

什么是热更新&#xff1f; 一种不需要用户关闭应用或重新启动设备就能进行的软件更新技术。它可以快速地在线修复或升级应用程序的错误或功能&#xff0c;从而减少用户的等待时间并提高用户体验。 如何优雅停止服务&#xff1f; Go 1.8版本之后&#xff0c; http.Server 内置…

Unity中URP下的SimpleLit的 BlinnPhong高光反射计算

文章目录 前言一、回顾Blinn-Phong光照模型1、Blinn-Phong模型&#xff1a; 二、URP下的SimpleLit的 BlinnPhong1、输入参数2、程序体计算 前言 在上篇文章中&#xff0c;我们分析了 URP下的SimpleLit的 Lambert漫反射计算。 Unity中URP下的SimpleLit的 Lambert漫反射计算 我…

Unity - 简单音频

“Test_04” AudioTest public class AudioTest : MonoBehaviour {// 声明音频// AudioClippublic AudioClip music;public AudioClip se;// 声明播放器组件private AudioSource player;void Start(){// 获取播放器组件player GetComponent<AudioSource>();// 赋值…

UI设计中的插画运用优势(下)

6. 插画赋予设计以美学价值&#xff0c;更容易被接受 即使所有人都在分析和争论产品的可用性和易用性&#xff0c;大家在对美的追求上&#xff0c;始终保持着一致的态度。一个设计是否具备可取性&#xff0c;是否能够通过甲方、客户和实际用户&#xff0c;是每个设计人都需要面…
最新文章