《GOF设计模式》—组合(COMPOSITE)—Delphi源码示例:声明管理子部件的操作(透明性设计)

示例:透明性设计

说明:

提供透明性的唯一方法是在Component中定义缺省AddRemove操作。这又带来了一个新的问题:Component.Add的实现不可避免地会有失败的可能性。你可以不让Component.Add做任何事情,但这就忽略了一个很重要的问题:企图向叶节点中增加一些东西时可能会引入错误。这时Add操作会产生垃圾。你可以让Add操作删除它的参数,但可能客户并不希望这样。

如果该组件不允许有子部件,或者Remove的参数不是该组件的子节点时,通常最好使用缺省方式(可能是产生一个异常)处理AddRemove的失败。

另一个办法是对“删除”的含义作一些改变。如果该组件有一个父部件引用,我们可重新定义Component.Remove,在它的父组件中删除掉这个组件。然而,对应的Add操作仍然没有合理的解释。

 

代码:

unit uComposite4;

 

interface

 

uses

    SysUtils,Dialogs;

 

type

    TComponent = class

    protected

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

        function GetCount: integer; 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

    raise Exception.Create('不支持该方法');

end;

 

procedure TComponent.Remove(AComponent: TComponent);

begin

    raise Exception.Create('不支持该方法');

end;

 

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

begin

    Result := nil;

end;

 

function TComponent.GetCount: integer;

begin

    Result := 0;

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;

var

    i: integer;

begin

    ShowMessage('Composite');

    //---

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

        FChilds[i].Operation;

end;

 

end.

 

procedure TForm1.Button1Click(Sender: TObject);

    //---

    function _GetComposite: TComponent;

    begin

        Result := TComposite.Create;

    end;

    //---

    function _GetComposite1: TComponent;

    begin

        Result := TLeaf.Create;

    end;

var

    AComponent: TComponent;

begin

    AComponent := _GetComposite1;

    try

        AComponent.Add(TLeaf.Create);

        AComponent.Operation;

    finally

        AComponent.Free;

    end;

end;

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值