《GOF设计模式》—中介者 (MEDIATOR)—Delphi源码示例:Colleague—Mediator通信(使用观察者模式)

来源:互联网 发布:复杂网络可控性 编辑:程序博客网 时间:2024/05/16 19:20

示例:Colleague—Mediator通信(使用观察者模式)
说明:
当一个感兴趣的事件发生时,Colleague必须与其Mediator通信。一种实现方法是使用观察者模式(Observer),将Mediator实现为一个Observer,各Colleague作为Subject,一旦其状态改变就发送通知给Mediator。Mediator作出的响应是将状态改变的结果传播给其他的Colleague。

代码:
unit uObserver;

interface

uses classes;

type
    TObserver = class;

    TSubjectData = class
    protected
        FObservers: TList;
        FNotifyEnabled: Boolean;
        procedure SetEnableNotify(AEnable: Boolean);
    public
        constructor Create;
        destructor Destroy; override;
        //---
        procedure Attach(AObserver: TObserver);
        procedure Detach(AObserver: TObserver);
        //---
        property NotifyEnabled: Boolean read FNotifyEnabled write SetEnableNotify;
    end;

    TObserver = class
    private
        FDatas: TList;
    public
        constructor Create;
        destructor Destroy; override;
        //---
        procedure Attach(AData: TSubjectData);
        procedure Detach(AData: TSubjectData);
        //---
        procedure Update(AData: TSubjectData); virtual;abstract;
    end;

implementation

constructor TSubjectData.Create;
begin
    FObservers := TList.Create;
end;

destructor TSubjectData.Destroy;
    //---
    procedure _DetachAll;
    var
        i:Integer;
    begin
        with FObservers do
        begin
            for i := Count - 1 downto 0 do
                TObserver(Items[i]).Detach(self);
        end;
    end;
begin
    _DetachAll;
    FObservers.Free;
    //---
    inherited;    
end;

procedure TSubjectData.Attach(AObserver: TObserver);
begin
    FObservers.Add(AObserver);
end;

procedure TSubjectData.Detach(AObserver: TObserver);
begin
    FObservers.Remove(AObserver);
end;

procedure TSubjectData.SetEnableNotify(AEnable: Boolean);
    //---
    procedure _NotifyObservers;
    var
        i: integer;
    begin
        with FObservers do
        begin
            for i := 0 to Count - 1 do
                TObserver(Items[i]).Update(self);
        end;
    end;
begin
    FNotifyEnabled := AEnable;
    if FNotifyEnabled then _NotifyObservers;
end;

constructor TObserver.Create;
begin
    FDatas := TList.Create;
end;

destructor TObserver.Destroy;
    //---
    procedure _DetachAll;
    var
        i:Integer;
    begin
        with FDatas do
        begin
            for i := Count - 1 downto 0 do
                TSubjectData(Items[i]).Detach(self);
        end;
    end;
begin
    _DetachAll;
    FDatas.Free;
    //---
    inherited;
end;

procedure TObserver.Attach(AData: TSubjectData);
begin
    FDatas.Add(AData);
    AData.Attach(self);
end;

procedure TObserver.Detach(AData: TSubjectData);
begin
    FDatas.Remove(AData);
    AData.Detach(self);
end;

end.

unit uMediatorObserver;

interface

uses
    SysUtils, Dialogs,uObserver;

type
    TMediator = class;

    TColleague = class(TSubjectData)
    end;
    TConcreteColleague1 = class(TColleague)
    private
        FValue: Integer;
        procedure SetValue(const Value: Integer);
    public
        property Value: Integer read FValue write SetValue;
    end;
    TConcreteColleague2 = class(TColleague)
    private
        FValue: Integer;
        procedure SetValue(const Value: Integer);
    public
        property Value: Integer read FValue write SetValue;
    end;

    TMediator = class(TObserver)
    end;
    TConcreteMediator = class(TMediator)
    private
        FColleague1: TConcreteColleague1;
        FColleague2: TConcreteColleague1;
    public
        constructor Create;
        destructor Destroy; override;
        //---
        procedure Update(AData: TSubjectData); override;
        procedure Calc;
    end;

procedure Test;

implementation

procedure Test;
var
    AMediator: TConcreteMediator;
begin
    AMediator := TConcreteMediator.Create;
    AMediator.Calc;
    AMediator.Free;
end;

procedure TConcreteColleague1.SetValue(const Value: Integer);
begin
    FValue := Value;
    //---
    self.NotifyEnabled := true;
end;

procedure TConcreteColleague2.SetValue(const Value: Integer);
begin
    FValue := Value;
    //---
    self.NotifyEnabled := true;
end;

procedure TConcreteMediator.Calc;
begin
    FColleague1.Value := 1;
end;

procedure TConcreteMediator.Update(AData: TSubjectData);
begin
    if AData = FColleague1 then
        FColleague2.Value := FColleague1.Value + 2
    else if AData = FColleague2 then
        ShowMessage(IntToStr(FColleague2.Value));
end;

constructor TConcreteMediator.Create;
begin
    inherited;
    //---
    FColleague1 := TConcreteColleague1.Create;
    self.Attach(FColleague1);
    //---
    FColleague2 := TConcreteColleague1.Create;
    self.Attach(FColleague2);
end;

destructor TConcreteMediator.Destroy;
    //---
    procedure _Free(AColleague: TColleague);
    begin
        if AColleague <> nil then
            AColleague.Free;
    end;
begin
    _Free(FColleague1);
    _Free(FColleague2);
    //---
    inherited;
end;

end.


原创粉丝点击