示例:用于复合对象的外部迭代器
说明:
在Composite模式中的那些递归聚合结构上,外部迭代器可能难以实现,因为在该结构中不同对象处于嵌套聚合的多个不同层次,因此一个外部迭代器为跟踪当前的对象必须存储一条纵贯该Composite的路径。
代码:
unit uCompositeIterator;
interface
uses
SysUtils, Classes,Dialogs, Contnrs;
type
TIterator = class;
TComponent = class
private
FName: string;
protected
function GetCount: integer; virtual; abstract;
function GetItems(Index: integer): TComponent; virtual; abstract;
public
constructor Create(const AName: string);
//---
function CreateIterator(): TIterator; virtual; abstract;
//---
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;
public
function CreateIterator: TIterator; override;
end;
TComposite = class(TComponent)
private
FChilds: TObjectList;
protected
function GetCount: integer; override;
function GetItems(Index: integer): TComponent; override;
public
constructor Create(const AName: string);
destructor Destroy; override;
//---
procedure Add(AComponent: TComponent);
function CreateIterator: TIterator; override;
end;
TIterator = class
public
procedure First(); virtual; abstract;
procedure Next(); virtual; abstract;
function IsDone(): Boolean; virtual; abstract;
function CurrentItem(): TComponent; virtual; abstract;
end;
TCompositeIterator1 = class(TIterator)
private
FList: TList;
FCurrent: integer;
public
constructor Create(const AList: TList);
destructor Destroy; override;
//---
procedure First(); override;
procedure Next(); override;
function IsDone(): Boolean; override;
function CurrentItem: TComponent; override;
end;
TCompositeIterator2 = class(TIterator)
private
FComposite: TComposite;
FCurIterator: TIterator;
FCurrent: integer;
procedure GetCurIterator;
public
constructor Create(const AComposite: TComposite);
destructor Destroy; override;
//---
procedure First; override;
function IsDone: Boolean; override;
procedure Next; override;
function CurrentItem: TComponent; override;
end;
TCompositeIterator3 = class(TIterator)
private
FComposite: TComposite;
FCurrent: integer;
FCurIterator: TIterator;
FIsNewIterator: Boolean;
procedure GetCurIterator;
public
constructor Create(const AComposite: TComposite);
destructor Destroy; override;
//---
procedure First; override;
function IsDone: Boolean; override;
procedure Next; override;
function CurrentItem: TComponent; override;
end;
procedure Test;
implementation
procedure Test;
//---
procedure _ShowAggregate(I: TIterator);
begin
with I do
begin
First;
while not IsDone do
begin
ShowMessage(CurrentItem.Name);
Next;
end;
end;
end;
var
AComposite, AComposite1: TComposite;
AIterator: TIterator;
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;
//---
AIterator := AComposite.CreateIterator;
_ShowAggregate(AIterator);
AIterator.Free;
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;
//---外部迭代器
function _CreateIterator1: TIterator;
var
AList: TList;
//---
procedure _AddToList(AList: TList; AComponent: TComponent);
var
i: Integer;
begin
AList.Add(AComponent);
//---
with AComponent do
begin
for i := 0 to Count - 1 do
_AddToList(AList, Items[i]);
end;
end;
begin
AList := TList.Create;
_AddToList(AList, self);
//---
Result := TCompositeIterator1.Create(AList);
end;
//---外部迭代器
function _CreateIterator2: TIterator;
begin
Result := TCompositeIterator2.Create(self);
end;
//---外部迭代器
function _CreateIterator3: TIterator;
begin
Result := TCompositeIterator3.Create(self);
end;
begin
Result := _CreateIterator2;
end;
function TComposite.GetItems(Index: integer): TComponent;
begin
Result := TComposite(FChilds[Index]);
end;
function TComposite.GetCount: integer;
begin
Result := FChilds.Count;
end;
constructor TCompositeIterator1.Create(const AList: TList);
begin
FList := AList;
FCurrent := 0;
end;
procedure TCompositeIterator1.First;
begin
FCurrent := 0;
end;
procedure TCompositeIterator1.Next;
begin
FCurrent := FCurrent + 1;
end;
function TCompositeIterator1.IsDone: Boolean;
begin
Result := FCurrent >= FList.Count;
end;
function TCompositeIterator1.CurrentItem: TComponent;
begin
Result := FList.Items[FCurrent];
end;
function TLeaf.CreateIterator: TIterator;
begin
Result := nil;
end;
function TLeaf.GetCount: integer;
begin
Result := 0;
end;
function TLeaf.GetItems(Index: integer): TComponent;
begin
Result := nil;
end;
destructor TCompositeIterator1.Destroy;
begin
FList.Free;
//---
inherited;
end;
constructor TComponent.Create(const AName: string);
begin
FName := AName;
end;
constructor TCompositeIterator3.Create(const AComposite: TComposite);
begin
FComposite := AComposite;
FCurrent := 0;
FCurIterator := nil;
FIsNewIterator := False;
end;
function TCompositeIterator3.CurrentItem: TComponent;
begin
if (FCurIterator = nil) or FIsNewIterator then
Result := FComposite.Items[FCurrent]
else
Result := FCurIterator.CurrentItem;
end;
destructor TCompositeIterator3.Destroy;
begin
if FCurIterator <> nil then
FreeAndNil(FCurIterator);
//---
inherited;
end;
procedure TCompositeIterator3.First;
begin
FCurrent := 0;
//---
GetCurIterator;
if FCurIterator <> nil then
FCurIterator.First;
end;
procedure TCompositeIterator3.GetCurIterator;
begin
if FCurIterator <> nil then
FreeAndNil(FCurIterator);
//---
with FComposite do
begin
if (FCurrent >= 0) and (FCurrent < Count) then
begin
FCurIterator := Items[FCurrent].CreateIterator;
FIsNewIterator := FCurIterator <> nil;
end;
end;
end;
function TCompositeIterator3.IsDone: Boolean;
begin
Result := (FCurrent >= FComposite.Count);
//---
if FCurIterator <> nil then
Result := Result and FCurIterator.IsDone;
end;
procedure TCompositeIterator3.Next;
begin
if FIsNewIterator then
begin
FIsNewIterator := False;
Exit;
end;
//---
if (FCurIterator <> nil) then
begin
with FCurIterator do
begin
Next;
if not IsDone then
Exit;
end;
end;
//---
FCurrent := FCurrent + 1;
GetCurIterator;
end;
constructor TCompositeIterator2.Create(const AComposite: TComposite);
begin
FComposite := AComposite;
FCurrent := 0;
FCurIterator := nil;
end;
destructor TCompositeIterator2.Destroy;
begin
if FCurIterator <> nil then
FreeAndNil(FCurIterator);
//---
inherited;
end;
function TCompositeIterator2.CurrentItem: TComponent;
begin
if (FCurIterator = nil) then
Result := FComposite.Items[FCurrent]
else
Result := FCurIterator.CurrentItem;
end;
procedure TCompositeIterator2.First;
begin
FCurrent := 0;
//---
GetCurIterator;
if FCurIterator <> nil then
FCurIterator.First;
end;
procedure TCompositeIterator2.GetCurIterator;
begin
if FCurIterator <> nil then
FreeAndNil(FCurIterator);
//---
with FComposite do
begin
if (FCurrent >= 0) and (FCurrent < Count) then
FCurIterator := Items[FCurrent].CreateIterator;
end;
end;
function TCompositeIterator2.IsDone: Boolean;
begin
Result := (FCurrent >= FComposite.Count);
//---
if FCurIterator <> nil then
Result := Result and FCurIterator.IsDone;
end;
procedure TCompositeIterator2.Next;
begin
if (FCurIterator <> nil) then
begin
with FCurIterator do
begin
Next;
if not IsDone then
Exit;
end;
end;
//---
FCurrent := FCurrent + 1;
GetCurIterator;
end;
end.
《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:用于复合对象的外部迭代器
最新推荐文章于 2024-09-24 22:18:19 发布