我是靠谱客的博主 动听跳跳糖,最近开发中收集的这篇文章主要介绍C常用设计模式——迭代器模式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章首发于知乎专栏:

https://zhuanlan.zhihu.com/c_1136684995157577728

个人公众号TarysThink

 

模板方法模式之后讲迭代器模式(Iterator)再合适不过。我始终认为,迭代器模式是一种特殊的模板方法模式。看这一篇有困难的同学最好回头再看一下上一篇:模板方法模式,当然,我也会从头开始讲故事,不必过分担心必须有模板方法模式的基础。

这篇篇幅会比较长,所以我们就直入主题。

操场上排了一排小学生,既有数据结构是顺序链表,也就是说用链表遍历节点的方式去遍历这些小学生。有这个一个需求,遍历小学生,遍历到的节点执行操作:printf("今天天气真好%d"); printf("今天你也很好看%d");,%d的位置打印出节点结构下的变量a。李逵的函数实现如下:

void ForeachStudent()
{
    Node head = GetHeadNode();//获取头节点
    Node pos = head;
    ListForeach(head, pos)//遍历链表操作的封装
    {
        printf("今天天气真好%d", ((Student *)pos)->a));//节点结构体为Student,其第一个成员为Node
        printf("今天你也很好看%d", ((Student *)pos)->a));
    }
}

上面这段代码封装性很好,特别是对链表具体操作的封装。

此时又来一个需求,业务方案要求在代码中的另一处也遍历小学生队列,但打印内容不同:printf("今天真热%d"); printf("体育课真累%d");,%d的位置打印出节点结构下的变量b。李逵同学的函数实现如下:

void ForeachStudentSayHot()
{
    Node head = GetHeadNode();//获取头节点
    Node pos = head;
    ListForeach(head, pos)//遍历链表操作的封装
    {
        printf("今天真热%d", ((Student *)pos)->b));//节点结构体为Student,其第一个成员为Node
        printf("体育课真累%d", ((Student *)pos)->b));
    }
}

宋江同学一看,这不行,这个需求引入后,原来的函数名必须改,哪怕改成ForeachStudentSayNice也好。

宝玉一看,觉得他们境界太低,简单一看代码里这么多重复,“你们难道没有消除重复的冲动吗?”,宝玉代码如下:

typedef void (*Say)(Node pos);

ForeachStudent(Say say)
{
    Node head = GetHeadNode();//获取头节点
    Node pos = head;
    ListForeach(head, pos)//遍历链表操作的封装
    {
        say(pos);
    }
}

void SayNice(Node pos)
{
    printf("今天天气真好%d", ((Student *)pos)->a));//节点结构体为Student,其第一个成员为Node
    printf("今天你也很好看%d", ((Student *)pos)->a));
}

void SayHot(Node pos)
{
    printf("今天真热%d", ((Student *)pos)->b));//节点结构体为Student,其第一个成员为Node
    printf("体育课真累%d", ((Student *)pos)->b));
}

//第一处调用
ForeachStudent(SayNice);
//第二处调用
ForeachStudent(SayHot);

旁边的贾政同学道:”这个代码写得非常好,SayNice和SayHot完全感知不到学生列表的具体组织形式。将来某一天发现链表的结构无法满足需求,你可以很便捷地修改外层的数据结构遍历函数,内部的处理函数不需要修改,这就是迭代器模式的核心思想。文章开头说,迭代器模式与模板方法模式非常相似,就是在这种层面上的相似,我们可以把外层循环看做一个模板,那么这就是一个模板方法模式了。”

贾政继续道:“这个方法有一些缺点。假如你想在遍历循环里加入break和continue语句,而且不同调用点的break和continue条件不同,那么你就需要在入参里把具体处理都传进去,随着变化方向的增多,带来的管理的复杂度越来越难以控制,代码将很难看懂。”

扩展阅读:

程序员诸葛亮亮说:“熟练掌握上面宝玉同学的代码写法,已足够写好结构遍历的绝大多数代码。而且这种方法已经符合了迭代器模式的设计思想,按C语言思想描述起来也非常简单和实用。设计模式里讲的迭代器模式,比宝玉的代码稍复杂些,它提供了更多更复杂的功能。我们回看ForeachStudent函数,它内部调用了链表操作专门的ListForeach函数,而且获取了链表头节点,这意味着,当我们将链表改成数组时,这些都将是阻碍。那有没有办法把这些信息对ForeachStudent也隐藏起来呢?有,再做些抽象,我们下回分解”。

最后

以上就是动听跳跳糖为你收集整理的C常用设计模式——迭代器模式的全部内容,希望文章能够帮你解决C常用设计模式——迭代器模式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部