迭代器模式
今天聊的是行为设计模式中的迭代器模式,如果是做 Java 的对于迭代器肯定不陌生。因为迭代器模式是Java和.Net编程环境中非常常用的设计模式。它的定义如下
迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。
不知道为什么在 Delphi 的泛型容器中并没有提供这一类的东西。当然也可能是因为我的无知。。。。
# 角色构成
其实所谓的角色构成就是指由那些类组成,同时说明这些类都是什么关系。因为想不出合适的名字,又看到别人是这么称呼的,所以我也跟着叫了
迭代器角色(Iterator):一般来说会有这么三个方法:next()、hasNext()和remove()
具体迭代器角色(Concrete Iterator):实现迭代器接口中定义的方法,完成集合的迭代。
容器角色(Aggregate):一般是一个接口,提供一个iterator()方法,此处我们以数组为例,其实以什么容器类都可以
具体容器角色(ConcreteAggregate):实现抽象容器的抽象方法
类图如下(引子菜鸟教程):
# 应用场景
说完基础构成之后我们还要了解一下它的应用场景
访问一个聚合对象的内容而无须暴露它的内部表示。
需要为聚合对象提供多种遍历方式。
为遍历不同的聚合结构提供一个统一的接口。
和其他设计模式它也有自己的缺点:由于迭代器模式将存储数据和遍历数据的职责分离,增加新的聚合类需要对应增加新的迭代器类,类的个数成对增加
# 代码实现
代码在DelphiXE10.4.2环境下编译通过
unit uIterator;
interface
type
TNames = array [0 .. 1] of String;
// 迭代器接口
ITerator = Interface
['{BF2BE685-0193-4F92-9C77-1AF0B3D1D4DA}']
function HasNext(): boolean;
function Next(): string;
End;
// 抽象容器类
TContainer = class abstract
private
FNames: TNames;
public
property Names: TNames read FNames write FNames;
function GetIterator(): ITerator; virtual; abstract;
End;
// 容器实现类
TNameRepository = class(TContainer)
public
constructor Create();
function GetIterator(): ITerator; override;
end;
// 迭代器实现类
TNameIterator = class(TInterfacedObject, ITerator)
private
FIndex: Integer;
Container: TContainer;
public
function HasNext(): boolean;
function Next(): string;
constructor Create(Container: TContainer);
end;
implementation
{ TNameRepository }
constructor TNameRepository.Create;
begin
self.FNames[0] := '小黑';
self.FNames[1] := '小白';
end;
function TNameRepository.GetIterator: ITerator;
begin
Result := TNameIterator.Create(self);
end;
{ TNameRepository.TNameIterator }
constructor TNameIterator.Create(Container: TContainer);
begin
self.FIndex := 0;
self.Container := Container;
end;
function TNameIterator.HasNext: boolean;
begin
Result := false;
if (self.FIndex < length(self.Container.Names)) then begin
Result := true;
end;
end;
function TNameIterator.Next: string;
begin
Result := '';
if (self.HasNext) then begin
Result := self.Container.Names[self.FIndex];
inc(self.FIndex);
end;
end;
end.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
调用
program ProjectIterator;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
uIterator in 'uIterator.pas';
begin
try
// 创建容器类对象
var
Repository := TNameRepository.Create();
// 获取迭代器对象
var
Iterator := Repository.GetIterator();
// 通过迭代器获取元素
while Iterator.hasNext do writeln(Iterator.Next);
except
on E: Exception do writeln(E.ClassName, ': ', E.Message);
end;
Readln;
end.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 小结一下
至此迭代器模式完成。我自己在学习设计模式的时候更多的是结合类图和代码。当看懂这两部分之后基本上就明白设计模式大概思路了。最后结合一下优缺点和适用场景。
最近重感冒了,调休在家实在没精神写文章和更新视频。今天终于感觉好点了