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

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

代码:
 
clip_image002
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.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值