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

示例:用于复合对象的外部迭代器
说明:
在Composite模式中的那些递归聚合结构上,外部迭代器可能难以实现,因为在该结构中不同对象处于嵌套聚合的多个不同层次,因此一个外部迭代器为跟踪当前的对象必须存储一条纵贯该Composite的路径。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值