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