《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:基于游标的迭代器

    技术2026-05-25  8

    示例:基于游标的迭代器 说明: 如果复合中的节点有一个接口可以从一个节点移到它的兄弟节点、父节点和子节点,那么基于游标的迭代器是个更好的选择。游标只需跟踪当前的节点;它可依赖这种节点接口来遍历该复合对象。 代码:   unit uCompositeCursor; interface uses Dialogs, Contnrs; type     TCursor = class;     TComponent = class     private         FName: string;         FParent: TComponent;     protected         function GetCount: integer; virtual; abstract;         function GetItems(Index: integer): TComponent; virtual; abstract;         function IndexOf(AItem: TComponent):Integer; virtual; abstract;         //---         procedure First(ACursor: TCursor);         procedure Next(ACursor: TCursor);         function IsDone(ACursor: TCursor): Boolean;     public         constructor Create(AParent: TComponent;const AName: string);         //---         function CreateCursor: TCursor;         //---         property Name: string read FName;         property Count: integer read GetCount;         property Items[Index: integer]: TComponent read GetItems; default;         property Parent: TComponent read FParent;     end;     TLeaf = class(TComponent)     protected         function GetCount: integer; override;         function GetItems(Index: integer): TComponent; override;         function IndexOf(AItem: TComponent): Integer; override;     end;     TComposite = class(TComponent)     private         FChilds: TObjectList;     protected         function GetCount: integer; override;         function GetItems(Index: integer): TComponent; override;         function IndexOf(AItem: TComponent): Integer; override;     public         constructor Create(AParent: TComponent;const AName: string);         destructor Destroy; override;         //---         procedure Add(AComponent: TComponent);     end;     TCursor = class     private         FComponent: TComponent;     public         constructor Create(const AComponent: TComponent);         //---         procedure First();         procedure Next();         function IsDone(): Boolean;         function CurrentItem: TComponent;     end; procedure Test; implementation procedure Test;     //---     procedure _ShowAggregate(I: TCursor);     begin         with I do         begin             First;             while not IsDone do             begin                 ShowMessage(CurrentItem.Name);                 Next;             end;         end;     end; var     AComposite, AComposite1: TComposite;     ACursor: TCursor; begin     AComposite := TComposite.Create(nil,'0');     try         with AComposite do         begin             AComposite1 := TComposite.Create(AComposite,'1');             with AComposite1 do             begin                 Add(TLeaf.Create(AComposite1,'11'));                 Add(TLeaf.Create(AComposite1,'12'));             end;             Add(AComposite1);             //---             AComposite1 := TComposite.Create(AComposite,'2');             with AComposite1 do             begin                 Add(TLeaf.Create(AComposite1,'21'));                 Add(TLeaf.Create(AComposite1,'22'));             end;             Add(AComposite1);             //---             Add(TLeaf.Create(AComposite,'3'));             Add(TLeaf.Create(AComposite,'4'));         end;         //---         ACursor := AComposite.CreateCursor;         _ShowAggregate(ACursor);         ACursor.Free;     finally         AComposite.Free;     end; end; constructor TComposite.Create(AParent: TComponent;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.GetItems(Index: integer): TComponent; begin     Result := TComposite(FChilds[Index]); end; function TComposite.GetCount: integer; begin     Result := FChilds.Count; end; function TComposite.IndexOf(AItem: TComponent): Integer; begin     Result := FChilds.IndexOf(AItem); end; function TLeaf.GetCount: integer; begin     Result := 0; end; function TLeaf.GetItems(Index: integer): TComponent; begin     Result := nil; end; function TLeaf.IndexOf(AItem: TComponent): Integer; begin     Result := -1; end; constructor TComponent.Create(AParent: TComponent;const AName: string); begin     FParent := AParent;     FName := AName; end; constructor TCursor.Create(const AComponent: TComponent); begin     FComponent := AComponent; end; procedure TCursor.Next; begin     FComponent.Next(self); end; function TCursor.IsDone: Boolean; begin     Result := FComponent.IsDone(self); end; function TCursor.CurrentItem: TComponent; begin     Result := FComponent; end; procedure TCursor.First; begin     FComponent.First(self); end; function TComponent.CreateCursor: TCursor; begin     Result := TCursor.Create(self); end; procedure TComponent.First(ACursor: TCursor); begin     ACursor.FComponent := self; end; function TComponent.IsDone(ACursor: TCursor): Boolean; begin     Result := (ACursor.FComponent = nil); end; procedure TComponent.Next(ACursor: TCursor);     //---     function _Next(AParent,AItem:TComponent):TComponent;     var         AIndex:Integer;     begin         if AParent = nil then             Result := nil         else         begin             with AParent do             begin                 AIndex := IndexOf(AItem);                 if (AIndex >= 0) and (AIndex < Count - 1) then                     Result := Items[AIndex + 1]                 else                     Result := _Next(AParent.Parent,AParent);             end;         end;     end; begin     if Self.Count > 0 then         ACursor.FComponent := Self.Items[0]     else if Self.Parent <> nil then         ACursor.FComponent := _Next(Self.Parent,self)     else         ACursor.FComponent := nil; end; end.

    最新回复(0)