《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:推模型(push model)

来源:互联网 发布:编程四大魔道天才 编辑:程序博客网 时间:2024/04/25 20:03

示例:推模型(push model)
说明:
目标向观察者发送关于改变的详细信息,而不管它们需要与否。

代码:
unit uPushModel;

interface

uses
  SysUtils, Classes, Dialogs;

type
    TSubjectState = record
        A,B:Integer;
    end;

    TObserver = class;

    TSubject = class
    private
        FObservers: TList;
        FState: TSubjectState;
    public
        constructor Create;
        destructor Destroy; override;
        //---
        procedure Attach(AObserver: TObserver);
        procedure Detach(AObserver: TObserver);
        procedure Notify;
    end;

    TConcreteSubject = class(TSubject)
    private
        function GetA: Integer;
        function GetB: Integer;
        procedure SetA(const Value: Integer);
        procedure SetB(const Value: Integer);
    public
        property A: Integer read GetA write SetA;
        property B: Integer read GetB write SetB;
    end;

    TObserver = class
    public
        procedure Update(AState: TSubjectState); virtual; abstract;
    end;

    TConcreteObserver = class(TObserver)
    protected
        FSubject: TSubject;
    public
        constructor Create(ASubject: TSubject);
        destructor Destroy; override;
        //---
        procedure Update(AState: TSubjectState); override;
    end;

procedure Test;

implementation

procedure Test;
var
    ASubject: TConcreteSubject;
    AObserver: TObserver;
begin
    ASubject := TConcreteSubject.Create;
    AObserver := TConcreteObserver.Create(ASubject);
    try
        ASubject.A := 1;
        ASubject.B := 2;
        ASubject.Notify;
    finally
        AObserver.Free;
        ASubject.Free;
    end;
end;

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

destructor TSubject.Destroy;
begin
    FObservers.Free;
    //---
    inherited;
end;

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

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

procedure TSubject.Notify;
var
    i: integer;
begin
    with FObservers do
    begin
        for i := 0 to Count - 1 do
            TObserver(Items[i]).Update(FState);
    end;
end;

constructor TConcreteObserver.Create(ASubject: TSubject);
begin
    FSubject := ASubject;
    if FSubject <> nil then FSubject.Attach(self);
end;

destructor TConcreteObserver.Destroy;
begin
    if FSubject <> nil then FSubject.Detach(self);
    //---
    inherited;
end;

procedure TConcreteObserver.Update(AState: TSubjectState);
begin
    ShowMessage(IntToStr(AState.A + AState.B))
end;

function TConcreteSubject.GetA: Integer;
begin
    Result := FState.A;
end;

function TConcreteSubject.GetB: Integer;
begin
    Result := FState.B;
end;

procedure TConcreteSubject.SetA(const Value: Integer);
begin
    FState.A := Value;
end;

procedure TConcreteSubject.SetB(const Value: Integer);
begin
    FState.B := Value;
end;

end.

原创粉丝点击