容器的主要职责有两个:存放元素和浏览元素。根据单一职责原则(SRP)要将二者分开,于是将浏览功能打包封装就有了迭代器。
用迭代器封装对动态数组的遍历:
1

2
{《HeadFirst设计模式》之迭代器模式 }3
{ 容器中的元素类 }4
{ 编译工具:Delphi7.0 }5
{ E-Mail :guzh-0417@163.com }6

7
unit uItem;8

9
interface10

11
type12
TMenuItem = class(TObject)13
private14
FName: String;15
FDescription: String;16
FVegetarian : Boolean;17
FPrice: Double;18
public19
constructor Create(aName, aDescription: String;20
aVegetarian : Boolean;21
aPrice: Double);22
function GetName: String;23
function GetDescription: String;24
function GetPrice: Double;25
function IsVegetarian: Boolean;26
end;27

28
implementation29

30
{ TMenuItem }31

32
constructor TMenuItem.Create(aName, aDescription: String;33
aVegetarian: Boolean;34
aPrice: Double);35
begin36
FName := aName;37
FDescription := aDescription;38
FVegetarian := aVegetarian;39
FPrice := aPrice;40
end;41

42
function TMenuItem.GetDescription: String;43
begin44
Result := FDescription;45
end;46

47
function TMenuItem.GetName: String;48
begin49
Result := FName;50
end;51

52
function TMenuItem.GetPrice: Double;53
begin54
Result := FPrice;55
end;56

57
function TMenuItem.IsVegetarian: Boolean;58
begin59
Result := FVegetarian;60
end;61

62
end.
1

2
{《HeadFirst设计模式》之迭代器模式 }3
{ 迭代器:封装对容器的遍历 }4
{ 编译工具:Delphi7.0 }5
{ E-Mail :guzh-0417@163.com }6

7
unit uIterator;8

9
interface10

11
uses12
uItem;13

14
type15
TMenuItems = array of TMenuItem;16
17
TIterator = class(TObject)18
public19
function HasNext: Boolean; virtual; abstract;20
function Next : TObject; virtual; abstract;21
end;22

23
TDinerMenuIterator = class(TIterator)24
private25
FMenuItem : TMenuItem;26
FMenuItems: TMenuItems;27
FPosition : Integer;28
public29
constructor Create(MenuItems: TMenuItems);30
function HasNext: Boolean; override;31
function Next : TObject; override;32
end;33

34
implementation35

36
{ TDinerMenuIterator }37

38
constructor TDinerMenuIterator.Create(MenuItems: TMenuItems);39
begin40
FMenuItems := MenuItems;41
end;42

43
function TDinerMenuIterator.HasNext: Boolean;44
begin45
if (FPosition < Length(FMenuItems)) and (FMenuItems[FPosition] <> nil) then46
Result := True47
else48
Result := False;49
end;50

51
function TDinerMenuIterator.Next: TObject;52
begin53
FMenuItem := FMenuItems[FPosition];54
FPosition := FPosition + 1 ;55
Result := FMenuItem;56
end;57

58
end.
1

2
{《HeadFirst设计模式》之迭代器模式 }3
{ 容器类及其用户: Waitress }4
{ 编译工具:Delphi7.0 }5
{ E-Mail :guzh-0417@163.com } 6

7
unit uAggregate;8

9
interface10

11
uses12
SysUtils, uItem, uIterator;13

14
type15
TMenu = class(TObject)16
public17
function CreateIterator: TIterator; virtual; abstract;18
end;19

20
TDinerMenu = class(TMenu)21
private22
FMenuItem : TMenuItem;23
FMenuItems: TMenuItems;24
FNumberOfItems: Integer;25
public26
constructor Create;27
destructor Destroy; override;28
procedure AddItem(aName, aDescription: String; aVegetarian: Boolean;29
aPrice: Double);30
function CreateIterator: TIterator; override;31
end;32

33
TWaitress = class(TObject)34
private35
FMenuItem : TMenuItem;36
FDinerMenu: TDinerMenu;37
DinerIterator: TIterator;38
public39
constructor Create(aDinerMenu: TDinerMenu);40
procedure PrintMenu; overload;41
procedure PrintMenu(aIterator: TIterator); overload;42
end;43
44
implementation45

46
const47
MAX_TIMES = 6;48

49
{ TDinerMenu }50

51
procedure TDinerMenu.AddItem(aName, aDescription: String; aVegetarian: Boolean;52
aPrice: Double);53
begin54
FMenuItem := TMenuItem.Create(aName, aDescription, aVegetarian, aPrice);55
if FNumberOfItems >= MAX_TIMES then56
Writeln('Sorry, menu is full! Can''t add item to menu')57
else58
begin59
FMenuItems[FNumberOfItems] := FMenuItem;60
FNumberOfItems := FNumberOfItems + 1;61
end;62
end;63

64
constructor TDinerMenu.Create;65
begin66
SetLength(FMenuItems, MAX_TIMES);67
68
AddItem('Vegetarian BLT',69
'Fakin Bacon with lettuce & tomato on whole Wheat', True, 2.99);70
AddItem('BLT',71
'Bacon with lettuce & tomato on whole Wheat', False, 2.99);72
AddItem('Soup of the day',73
'Soup of the day, with a side of potato salad', False, 3.29);74
AddItem('Hotdog',75
'A hot dog, with saurkraut, relish, onions, topped with cheese',76
False, 3.05);77
AddItem('Steamed Veggies and Brown Rice',78
'Steamed vegetables over brown rice', True, 3.99);79
AddItem('Pasta',80
'Spaghetti with Marinara Sauce, and a slice of sourdough bread', True,81
3.89);82
end;83

84
destructor TDinerMenu.Destroy;85
begin86
FreeAndNil(FMenuItem);87
inherited;88
end;89

90
function TDinerMenu.CreateIterator: TIterator;91
begin92
Result := TDinerMenuIterator.Create(FMenuItems);93
end;94

95
{ TWaitress }96

97
constructor TWaitress.Create(aDinerMenu: TDinerMenu);98
begin99
FDinerMenu := aDinerMenu;100
end;101

102
procedure TWaitress.PrintMenu;103
begin104
try105
DinerIterator := FDinerMenu.CreateIterator;106
Writeln('MENU');107
Writeln('----');108
Writeln('BREAKFAST');109
Writeln;110
PrintMenu(DinerIterator);111
finally112
FreeAndNil(DinerIterator);113
end;114
end;115

116
procedure TWaitress.PrintMenu(aIterator: TIterator);117
begin118
while (aIterator.HasNext) do119
begin120
FMenuItem := (aIterator.Next) as TMenuItem;121
Writeln(FMenuItem.GetName + ',');122
Writeln(FMenuItem.GetPrice, ' -- ');123
Writeln(FMenuItem.GetDescription);124
end;125
end;126

127
end.
1

2
{《HeadFirst设计模式》之迭代器模式 }3
{ 客户端 }4
{ 编译工具:Delphi7.0 }5
{ E-Mail :guzh-0417@163.com }6

7
program pMenuTestDrive;8

9
{$APPTYPE CONSOLE}10

11
uses12
SysUtils,13
uItem in 'uItem.pas',14
uAggregate in 'uAggregate.pas',15
uIterator in 'uIterator.pas';16

17
var18
DinerMenu: TDinerMenu;19
Waitress : TWaitress;20

21
begin22
DinerMenu := TDinerMenu.Create;23
Waitress := TWaitress.Create(DinerMenu);24
Waitress.PrintMenu;25

26
FreeAndNil(DinerMenu);27
FreeAndNil(Waitress);28
Readln;29
end.
运行结果:
特别感谢:在实现上面示例时,遇到动态数组做参数的问题。感谢盒子论坛里的ZuoBaoQuan兄出手相助!
浙公网安备 33010602011771号