《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:用于复合对象的内部迭代器

    技术2026-05-21  6

    示例:用于复合对象的内部迭代器 说明: 有时使用一个内部迭代器会更容易一些。它仅需递归地调用自己即可,这样就隐式地将路径存储在调用栈中,而无需显式地维护当前对象位置。 代码:   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.

    最新回复(0)