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