迭代器(Iterator)模式,又叫做游标(Cursor)模式。提供一种方法访问一个容器(container)或者聚集(Aggregator)对象中各个元素,而又不需暴露该对象的内部细节。在采用不同的方式迭代时,只需要替换相应Iterator类即可。本文采用Matlab语言实现对元胞数组和string数组的遍历。

Aggregator.m

classdef Aggregator < handle
methods(Abstract)
iterObj = createIterator(~);
end
end

CellAggregator.m

classdef CellAggregator < Aggregator
properties
cell
end
methods
function obj = CellAggregator(cell)
obj.cell = cell;
end
function iterObj = createIterator(obj)
iterObj = CellIterator(obj);
end
end
end

StringAggregator.m

classdef StringAggregator < Aggregator
properties
string_arr
end
methods
function obj = StringAggregator(string_arr)
obj.string_arr = string_arr;
end
function iterObj = createIterator(obj)
iterObj = StringIterator(obj);
end
end
end

Iterator.m

classdef Iterator < handle
methods(Abstract)
hasNext(~);
next(~);
end
end

CellIterator.m

classdef CellIterator < Iterator
properties
index = 1;
aggHandle;
end
methods
function obj = CellIterator(agg)
obj.aggHandle = agg;
end
function res = hasNext(obj)
if(obj.index <= length(obj.aggHandle.cell))
res = true;
else
res = false;
end
end
function ele = next(obj)
if(obj.hasNext())
ele = obj.aggHandle.cell{obj.index};
obj.index = obj.index + 1;
else
ele = [];
end
end
end
end

StringIterator.m

classdef StringIterator < Iterator
properties
index = 1;
aggHandle;
end
methods
function obj = StringIterator(agg)
obj.aggHandle = agg;
end
function res = hasNext(obj)
if(obj.index <= obj.aggHandle.string_arr.length)
res = true;
else
res = false;
end
end
function ele = next(obj)
if(obj.hasNext())
ele = obj.aggHandle.string_arr(obj.index);
obj.index = obj.index + 1;
else
ele = string.empty();
end
end
end
end

 测试代码:

cell = CellAggregator({'matlab','cell','iter'});
iterObj = cell.createIterator();
while iterObj.hasNext()
disp(iterObj.next());
end str_arr = StringAggregator(["matlab","string","iter"]);
iterObj = str_arr.createIterator();
while iterObj.hasNext()
disp(iterObj.next());
end

迭代器模式不仅可以对集合进行顺序遍历,而且可以以用户想要的条件进行遍历,如果想要统计列表中所有偶数的和,可以写成循环语句,如下所示:

test_for.m

list = [13,8,17,11,8,19,18,12,13,12];

sum = 0;
for i=1:length(list)
if mod(list(i),2) == 0
sum = sum + list(i);
end
end disp("列表中所有偶数的和:" + sum); sum = 0;
for i=1:length(list)
if mod(list(i),2) == 1
sum = sum + list(i);
end
end disp("列表中所有奇数的和:" + sum);

如果要统计列表中所有奇数的和,这就需要对循环语句块进行修改,如上所示。这就违反了对修改关闭的原则。而迭代器模式可以将循环语句块和业务语句块(sum求和)分离出去,这就需要对Aggregator和Iterator类进行继承,如下所示:

ListAggregator.m

classdef ListAggregator < Aggregator
properties(Constant)
EVEN_ITER = 0
ODD_ITER = 1
end
properties
list
end
methods
function obj = ListAggregator(list)
obj.list = list;
end
function iterObj = createIterator(obj,type_iter)
if(type_iter == ListAggregator.EVEN_ITER)
iterObj = EvenIterator(obj);
else
iterObj = OddIterator(obj);
end
end
end
end

OddIterator.m

classdef OddIterator < Iterator
properties
index = 1;
aggHandle;
end
methods
function obj = OddIterator(agg)
obj.aggHandle = agg;
end
function res = hasNext(obj)
res = false;
while(obj.index <= length(obj.aggHandle.list))
if mod(obj.aggHandle.list(obj.index),2) == 1
res = true;
break;
end
obj.index = obj.index + 1;
end
end
function ele = next(obj)
if(obj.hasNext())
ele = obj.aggHandle.list(obj.index);
obj.index = obj.index + 1;
else
ele = [];
end
end
end
end

EvenIterator.m

classdef EvenIterator < Iterator
properties
index = 1;
aggHandle;
end
methods
function obj = EvenIterator(agg)
obj.aggHandle = agg;
end
function res = hasNext(obj)
res = false;
while(obj.index <= length(obj.aggHandle.list))
if mod(obj.aggHandle.list(obj.index),2) == 0
res = true;
break;
end
obj.index = obj.index + 1;
end
end
function ele = next(obj)
if(obj.hasNext())
ele = obj.aggHandle.list(obj.index);
obj.index = obj.index + 1;
else
ele = [];
end
end
end
end

test_iter.m

list_agg = ListAggregator([13,8,17,11,8,19,18,12,13,12]);
iterObj = list_agg.createIterator(ListAggregator.EVEN_ITER);
sum = 0;
while iterObj.hasNext()
sum = sum + iterObj.next();
end
disp("列表中所有偶数的和:" + sum); iterObj = list_agg.createIterator(ListAggregator.ODD_ITER);
sum = 0;
while iterObj.hasNext()
sum = sum + iterObj.next();
end
disp("列表中所有奇数的和:" + sum);

如果需要返回列表标,可以将next函数的返回值定义成[ele,index] = next(obj),python里面有yield关键字,可以让迭代器模式更加简洁,见参考资料。

迭代器模式还可以扁平化多层嵌套循环,如果找到所有水仙花数,可以使用三层循环,代码如下:

test_for.m

a = 1:9;
b = 0:9;
c = 0:9; for i=1:length(a)
for j = 1:length(b)
for k = 1:length(c)
num = a(i)*100 + b(j)*10 + c(k);
if a(i)^3 + b(j)^3 + c(k)^3 == a(i)*100 + b(j)*10 + c(k)
disp("" + num + "是水仙花数");
end
end
end
end

如果使用迭代器模式来简化三层循环,只需要对Aggregator和Iterator类进行继承,代码如下:

MutiListAggregator.m

classdef MutiListAggregator < Aggregator
properties
lists
end
methods
function obj = MutiListAggregator(varargin)
obj.lists = varargin;
end
function iterObj = createIterator(obj)
iterObj = MutiListIterator(obj);
end
end
end

MutiListIterator.m

classdef MutiListIterator < Iterator
properties
indexs = [];
lengths = [];
aggHandle;
end
methods
function obj = MutiListIterator(agg)
obj.aggHandle = agg;
for i= 1:length(obj.aggHandle.lists)
obj.lengths(i) = length(obj.aggHandle.lists{i});
end
obj.indexs = ones(1,length(obj.aggHandle.lists));
end
function res = hasNext(obj)
if(obj.indexs(1) > obj.lengths(1))
res = false;
else
res = true;
end
end
function varargout = next(obj)
if(obj.hasNext())
for i = 1:length(obj.aggHandle.lists)
temp_list = obj.aggHandle.lists{i};
varargout{i} = temp_list(obj.indexs(i));
end
obj.indexs(length(obj.aggHandle.lists)) = obj.indexs(length(obj.aggHandle.lists)) + 1;
for i = length(obj.aggHandle.lists):-1:2
if(obj.indexs(i) > obj.lengths(i))
obj.indexs(i) = mod(obj.indexs(i), obj.lengths(i));
obj.indexs(i - 1) = obj.indexs(i - 1) + 1;
end
end
else
for i = 1:length(obj.aggHandle.lists)
varargout{i} = [];
end
end
end
end
end

test_iter.m

list_agg = MutiListAggregator(1:9,0:9,0:9);
iterObj = list_agg.createIterator();
while iterObj.hasNext()
[a,b,c] = iterObj.next();
num = a * 100 + b * 10 + c;
if a^3 + b^3 + c^3 == a * 100 + b * 10 + c
disp("" + num + "是水仙花数");
end
end

参考资料:

https://mp.weixin.qq.com/s/tghaVkTPUijBJO0qxSXdZQ

Matlab迭代器模式的更多相关文章

  1. C#设计模式-迭代器模式

    一. 迭代器(Iterator)模式 迭代器是针对集合对象而生的,对于集合对象而言,必然涉及到集合元素的添加删除操作,同时也肯定支持遍历集合元素的操作,我们此时可以把遍历操作也放在集合对象中,但这样的 ...

  2. 设计模式(十):从电影院中认识"迭代器模式"(Iterator Pattern)

    上篇博客我们从醋溜土豆丝与清炒苦瓜中认识了“模板方法模式”,那么在今天这篇博客中我们要从电影院中来认识"迭代器模式"(Iterator Pattern).“迭代器模式”顾名思义就是 ...

  3. 迭代器模式/iterator模式/对象行为型模式

    意图 又名:游标(Cursor): 提供一种方法顺序访问一个聚合对象中各个元素,而又不暴露该对象的内部表示. 动机 一个聚合对象,提供访问元素的方法,而有不暴露它的内部结构.如list,将对列表的访问 ...

  4. C#设计模式系列:迭代器模式(Iterator)

    迭代器模式把对象的职责分离,职责分离可以最大限度减少彼此之间的耦合程度,从而建立一个松耦合的对象.职责分离的要点是对被分离的职责进行封装,并以抽象的方式建立彼此之间的关系. 1.迭代器模式简介 1.1 ...

  5. php实现设计模式之 迭代器模式

    <?php /*迭代器模式: 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示.(行为模式) * 1.迭代器角色(Iterator):迭代器角色负责定义访问和遍历元素的 ...

  6. Java源代码-迭代器模式

    Java无疑是最成功的项目之一了,而在其中学习设计模式和架构设计,无疑是最好不过了. 概念: 提供一种方法访问容器中的各个元素,而又不暴露该对象的内部细节. 使用场景: 和容器经常在一起,我们定义了一 ...

  7. PHP设计模式 迭代器模式

    迭代器模式,在不需要了解内部实现的前提下,遍历一个聚合对象的内部元素.相比于传统的编程模式,迭代器模式可以隐藏遍历元素所需要的操作. AllHacl.php <?php namespace Ba ...

  8. [Head First设计模式]生活中学设计模式——迭代器模式

    系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...

  9. js设计模式总结-迭代器模式

    迭代器模式 要解决的问题 迭代器要解决的问题很简单很单纯,就是进行遍历操作. 实现原理 基本所有语言都实现了迭代器,javascript也不例外,如Array.prototype.forEach,fo ...

随机推荐

  1. 第08组 Beta冲刺(3/4)

    队名 八组评分了吗 组长博客链接(2分) 组员1李昕晖(组长) 过去两天完成了哪些任务 文字/口头描述 了解各个小组的进度与难以攻破的地方,晚上安排开会,安排新的冲刺任务. 重新分配小组及个人任务. ...

  2. Linux系统下zookeeper客户端命令使用

    1. 启动客户端 [admin@yrjk bin]$ ./zkCli.sh [zk: localhost:2181(CONNECTED) 0] 2. 显示所有操作命令 [zk: localhost:2 ...

  3. android gradle使用阿里源

    使用阿里源 新建一个init.gradle 文件到$USER_HOME/.gradle/目录下,这们就省的翻墙了. init.gradle 文件内容如下: allprojects { reposito ...

  4. ThinkPHP 5.1 跨域中间件

    <?php namespace app\http\middleware; class CrossDomain { public function handle($request, \Closur ...

  5. java agent 详细介绍 -javaagent参数

    java agent 详细介绍 简介 java agent是java命令的一个参数.参数 javaagent 可以用于指定一个 jar 包,并且对该 java 包有2个要求: 这个 jar 包的MAN ...

  6. Nginx实践篇(5)- Nginx代理服务 - 代理缓冲区、代理重新定义请求头、代理连接超时(转)

    Nginx实践篇(5)- Nginx代理服务 - 代理缓冲区.代理重新定义请求头.代理连接超时 nginx参数默认值 http://nginx.org/en/docs/http/ngx_http_co ...

  7. openvswitch2.11.0修改源码后重新编译

    一:推文 https://www.jianshu.com/p/923f49c290f5(可以删除运行当中的DataPath内核) https://github.com/ebiken/doc-netwo ...

  8. Nginx添加静态页面

    1.编辑配置文件 sudo vim /etc/nginx/nginx.conf 在http {}中添加如下 server { listen 80; server_name localhost; loc ...

  9. K8S使用入门-添加一个node

    上一篇博客我们已经将K8S部署起来了,现在我们就来介绍一下如何简单使用K8S (1)添加节点 注意事项:不能和k8s master节点的主机名一样.否则会导致k8s无法正常识别出该节点 添加节点是比较 ...

  10. Prometheus监控教程——从入门到放弃

    Prometheus的安装还是比较简单的 下载地址如下 https://prometheus.io/download/ 解压,修改配置,运行.默认监听9090端口 [root@localhost ~] ...