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

来源:互联网 发布:怎样备份电脑数据库 编辑:程序博客网 时间:2024/05/17 06:34

示例:基于游标的迭代器
说明:
如果复合中的节点有一个接口可以从一个节点移到它的兄弟节点、父节点和子节点,那么基于游标的迭代器是个更好的选择。游标只需跟踪当前的节点;它可依赖这种节点接口来遍历该复合对象。

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

原创粉丝点击