示例:用于复合对象的内部迭代器
说明:
有时使用一个内部迭代器会更容易一些。它仅需递归地调用自己即可,这样就隐式地将路径存储在调用栈中,而无需显式地维护当前对象位置。
代码:
unit uCompositeIterator1;
interface
uses
Dialogs, Contnrs;
type
TIterator = class;
TComponent = class
private
FName: string;
protected
function GetCount: integer; virtual; abstract;
function GetItems(Index: integer): TComponent; virtual; abstract;
//---
function CreateIterator(): TIterator; virtual; abstract;
procedure ProcessItem(AItem: TComponent); virtual;
public
constructor Create(const AName: string);
//---
procedure Traverse();overload;
procedure Traverse(AItem: TComponent);overload;
//---
property Name: string read FName;
property Count: integer read GetCount;
property Items[Index: integer]: TComponent read GetItems; default;
end;
TLeaf = class(TComponent)
protected
function GetCount: integer; override;
function GetItems(Index: integer): TComponent; override;
//---
function CreateIterator: TIterator; override;
end;
TComposite = class(TComponent)
private
FChilds: TObjectList;
protected
function GetCount: integer; override;
function GetItems(Index: integer): TComponent; override;
//---
function CreateIterator: TIterator; override;
public
constructor Create(const AName: string);
destructor Destroy; override;
//---
procedure Add(AComponent: TComponent);
end;
TIterator = class
public
procedure First(); virtual; abstract;
procedure Next(); virtual; abstract;
function IsDone(): Boolean; virtual; abstract;
function CurrentItem(): TComponent; virtual; abstract;
end;
TCompositeIterator = class(TIterator)
private
FComposite: TComposite;
FCurrent: integer;
public
constructor Create(const AComposite: TComposite);
//---
procedure First; override;
function IsDone: Boolean; override;
procedure Next; override;
function CurrentItem: TComponent; override;
end;
TNullIterator = class(TIterator)
public
procedure First; override;
function IsDone: Boolean; override;
procedure Next; override;
function CurrentItem: TComponent; override;
end;
procedure Test;
implementation
procedure Test;
var
AComposite, AComposite1: TComposite;
begin
AComposite := TComposite.Create('0');
try
with AComposite do
begin
AComposite1 := TComposite.Create('1');
with AComposite1 do
begin
Add(TLeaf.Create('11'));
Add(TLeaf.Create('12'));
end;
Add(AComposite1);
//---
AComposite1 := TComposite.Create('2');
with AComposite1 do
begin
Add(TLeaf.Create('21'));
Add(TLeaf.Create('22'));
end;
Add(AComposite1);
//---
Add(TLeaf.Create('3'));
Add(TLeaf.Create('4'));
end;
//---
AComposite.Traverse;
//AComposite.Traverse(AComposite);
finally
AComposite.Free;
end;
end;
constructor TComposite.Create(const AName: string);
begin
inherited;
//---
FChilds := TObjectList.Create;
end;
destructor TComposite.Destroy;
begin
FChilds.Free;
//---
inherited;
end;
procedure TComposite.Add(AComponent: TComponent);
begin
FChilds.Add(AComponent);
end;
function TComposite.CreateIterator: TIterator;
begin
Result := TCompositeIterator.Create(self);
end;
function TComposite.GetItems(Index: integer): TComponent;
begin
Result := TComposite(FChilds[Index]);
end;
function TComposite.GetCount: integer;
begin
Result := FChilds.Count;
end;
function TLeaf.CreateIterator: TIterator;
begin
Result := TNullIterator.Create;
end;
function TLeaf.GetCount: integer;
begin
Result := 0;
end;
function TLeaf.GetItems(Index: integer): TComponent;
begin
Result := nil;
end;
constructor TComponent.Create(const AName: string);
begin
FName := AName;
end;
constructor TCompositeIterator.Create(const AComposite: TComposite);
begin
FComposite := AComposite;
FCurrent := 0;
end;
function TCompositeIterator.CurrentItem: TComponent;
begin
Result := FComposite.Items[FCurrent];
end;
procedure TCompositeIterator.First;
begin
FCurrent := 0;
end;
function TCompositeIterator.IsDone: Boolean;
begin
Result := (FCurrent >= FComposite.Count);
end;
procedure TCompositeIterator.Next;
begin
FCurrent := FCurrent + 1;
end;
procedure TComponent.ProcessItem(AItem: TComponent);
begin
ShowMessage(AItem.Name);
end;
procedure TComponent.Traverse;
var
AIterator:TIterator;
begin
self.ProcessItem(self);
//---
AIterator := self.CreateIterator;
try
with AIterator do
begin
First;
while not IsDone do
begin
CurrentItem.Traverse;
Next;
end;
end;
finally
AIterator.Free;
end;
end;
procedure TComponent.Traverse(AItem: TComponent);
{递归调用}
var
AIterator:TIterator;
begin
self.ProcessItem(AItem);
//---
AIterator := AItem.CreateIterator;
try
with AIterator do
begin
First;
while not IsDone do
begin
self.Traverse(CurrentItem);
Next;
end;
end;
finally
AIterator.Free;
end;
end;
function TNullIterator.CurrentItem: TComponent;
begin
Result := nil;
end;
procedure TNullIterator.First;
begin
end;
function TNullIterator.IsDone: Boolean;
begin
Result := true;
end;
procedure TNullIterator.Next;
begin
end;
end.
《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:用于复合对象的内部迭代器
最新推荐文章于 2024-09-27 21:35:31 发布