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

    技术2026-05-11  3

    示例:用于复合对象的外部迭代器 说明: 在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.

    最新回复(0)