《GOF设计模式》—组合(COMPOSITE)—Delphi源码示例:最大化Component接口

来源:互联网 发布:ug产品编程技巧40条 编辑:程序博客网 时间:2024/05/01 00:02
示例:最大化Component接口

说明:

Composite模式的目的之一是使得用户不知道他们正在使用的具体的LeafComposite类。为了达到这一目的,Composite类应为LeafComposite类尽可能多定义一些公共操作。Composite类通常为这些操作提供缺省的实现,而LeafComposite子类可以对它们进行重定义。

然而,这个目标有时可能会与类层次结构设计原则相冲突,该原则规定:一个类只能定义那些对它的子类有意义的操作。有许多Component所支持的操作对Leaf类似乎没有什么意义,那么Component怎样为它们提供一个缺省的操作呢?

有时一点创造性可以使得一个看起来仅对Composite才有意义的操作,将它移入Component类中,就会对所有的Component都适用。例如,访问子节点的接口是Composite类的一个基本组成部分,但对Leaf类来说并不必要。但是如果我们把一个Leaf看成一个没有子节点的Component,就可以为在Component类中定义一个缺省的操作,用于对子节点进行访问,这个缺省的操作不返回任何一个子节点。Leaf类可以使用缺省的实现,而Composite类则会重新实现这个操作以返回它们的子类。

 

代码:

unit uComposite2;

 

interface

 

uses

    Dialogs;

 

type

    TComponent = class

    protected

        function GetCount: integer; virtual;

        function GetChilds(Index: integer): TComponent; virtual;

    public

        procedure Operation; virtual; abstract;

        procedure Add(AComponent: TComponent); virtual;

        procedure Remove(AComponent: TComponent); virtual;

        //---

        property Count: integer read GetCount;

        property Childs[Index: integer]: TComponent read GetChilds;

    end;

    TLeaf = class(TComponent)

    public

        procedure Operation; override;

    end;

    TComposite = class(TComponent)

    private

        FChilds: array of TComponent;

    protected

        function GetChilds(Index: integer): TComponent; override;

        function GetCount: integer; override;

    public

        constructor Create;

        destructor Destroy; override;

        //---

        procedure Operation; override;

        procedure Add(AComponent: TComponent); override;

        procedure Remove(AComponent: TComponent); override;

    end;

 

implementation

 

procedure TComponent.Add(AComponent: TComponent);

begin

end;

 

procedure TComponent.Remove(AComponent: TComponent);

begin

end;

 

procedure TLeaf.Operation;

begin

    ShowMessage('Leaf');

end;

 

constructor TComposite.Create;

begin

    SetLength(FChilds,0);

end;

 

destructor TComposite.Destroy;

    //---

    procedure _Clear;

    var

        i: integer;

    begin

        for i := low(FChilds) to high(FChilds) do

            FChilds[i].Free;

        SetLength(FChilds,0);

    end;

begin

    _Clear;

    //---

    inherited;

end;

 

procedure TComposite.Add(AComponent: TComponent);

var

    ACount: integer;

begin

    ACount := Length(FChilds);

    SetLength(FChilds,ACount + 1);

    FChilds[ACount] := AComponent;

end;

 

procedure TComposite.Remove(AComponent: TComponent);

    //---

    function _IndexOf: integer;

    var

        i: integer;

    begin

        for i := low(FChilds) to high(FChilds) do

        begin

            if FChilds[i] = AComponent then

            begin

                Result := i;

                exit;

            end;

        end;

        //---

        Result := -1;

    end;

    //---

    procedure _Delete(AIndex: integer);

    var

        ACount: integer;

    begin

        ACount := Length(FChilds);

        if AIndex < ACount - 1 then

            Move(FChilds[AIndex + 1],FChilds[AIndex],(ACount - AIndex - 1) * 4);

        SetLength(FChilds,ACount - 1);

    end;

var

    AIndex: integer;

begin

    AIndex := _IndexOf;

    if AIndex >= 0 then

        _Delete(AIndex);

end;

 

function TComposite.GetChilds(Index: integer): TComponent;

begin

    Result := FChilds[Index];

end;

 

function TComposite.GetCount: integer;

begin

    Result := Length(FChilds);

end;

 

procedure TComposite.Operation;

begin

    ShowMessage('Composite');

end;

 

function TComponent.GetChilds(Index: integer): TComponent;

begin

    Result := nil;

end;

 

function TComponent.GetCount: integer;

begin

    Result := 0;

end;

 

end.

 

procedure TForm1.Button1Click(Sender: TObject);

    //---

    function _GetComposite: TComponent;

    begin

        Result := TComposite.Create;

        with Result do

        begin

            Add(TLeaf.Create);

            Add(TLeaf.Create);

            Add(TComposite.Create);

        end;

    end;

    //---

    function _GetComposite1: TComponent;

    begin

        Result := TLeaf.Create;

    end;

    //---

    procedure _ShowComposite(AComponent: TComponent);

    var

        i: integer;

    begin

        AComponent.Operation;

        for i := 0 to AComponent.Count - 1 do

            AComponent.Childs[i].Operation;

    end;

var

    AComposite: TComponent;

begin

    AComposite := _GetComposite;

    try

        _ShowComposite(AComposite);

    finally

        AComposite.Free;

    end;

end;

 

原创粉丝点击