《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:时钟

    技术2022-05-19  28

    示例:时钟 说明: ClockTimer是一个用于存储和维护一天时间的具体目标。它每秒钟通知一次它的观察者。 我们定义一个DigitalClock类来显示时间。它从一个用户界面工具箱提供的Widget类继承了它的图形功能。 代码: 迭代器uListIterator unit uListIterator; interface uses classes; type     TListIterator = class     private         FList: TList;         FCurrent: integer;     public         constructor Create(const AList: TList);         //---         procedure First();         procedure Next();         function IsDone: Boolean;         function CurrentItem: Pointer;     end; implementation constructor TListIterator.Create(const AList: TList); begin     FList := AList;     FCurrent := 0; end; procedure TListIterator.First(); begin     FCurrent := 0; end; procedure TListIterator.Next(); begin     FCurrent := FCurrent + 1; end; function TListIterator.IsDone: Boolean; begin     Result := FCurrent >= FList.Count; end; function TListIterator.CurrentItem: Pointer; begin     if IsDone() then         Result := nil     else         Result := FList.Items[FCurrent]; end; end. 观察者uObserver1 unit uObserver1; interface uses classes; type     TSubject = class;     IObserver = interface         ['{7A3926C5-A58F-4FE3-9798-D1C05DB668B0}']         procedure Update(theChangedSubject: TSubject);     end;     TSubject = class     private         FObservers: TList;     public         constructor Create;         destructor Destroy; override;         //---         procedure Attach(AObserver: IObserver);         procedure Detach(AObserver: IObserver);         procedure Notify();     end; implementation uses uListIterator; constructor TSubject.Create; begin     inherited;     //---     FObservers := TList.Create; end; destructor TSubject.Destroy; begin     FObservers.Free;     //---     inherited; end; procedure TSubject.Attach(AObserver: IObserver); begin     FObservers.Add(Pointer(AObserver)); end; procedure TSubject.Detach(AObserver: IObserver); begin     FObservers.Remove(Pointer(AObserver)); end; procedure TSubject.Notify(); var     AIterator: TListIterator; begin     AIterator := TListIterator.Create(FObservers);     try         with AIterator do         begin             First;             while not IsDone() do             begin                 IObserver(CurrentItem).Update(Self);                 Next();             end;         end;     finally         AIterator.Free;     end; end; end. 时钟uClock   unit uClock; interface uses     SysUtils, Classes, Graphics, Controls,     ExtCtrls, DateUtils, uObserver1; type     TClockTimer = class(TSubject)     private         FTimer: TTimer;         FTime: TDateTime;         procedure DoTimer(Sender: TObject);     public         constructor Create;         destructor Destroy; override;         //---         function GetHour(): integer;         function GetMinute: integer;         function GetSecond: integer;         procedure Tick();     end;     TWidget = class(TGraphicControl)     protected         procedure Paint; override;     public         procedure Draw(); virtual; abstract;     end;     TDigitClock = class(TWidget, IObserver)     private         FSubject: TClockTimer;     public         constructor Create(AOwner: TComponent; const ASubject: TClockTimer); reintroduce;         destructor Destroy; override;         //---         procedure Draw(); override;         procedure IObserver.Update = IUpdate;         procedure IUpdate(theChangedSubject: TSubject);     end;     TAnalogClock = class(TWidget, IObserver)     private         FSubject: TClockTimer;     public         constructor Create(AOwner: TComponent; const ASubject: TClockTimer);             reintroduce;         destructor Destroy; override;         //---         procedure Draw; override;         procedure IObserver.Update = IUpdate;         procedure IUpdate(theChangedSubject: TSubject);     end; implementation constructor TClockTimer.Create; begin     inherited;     //---     FTimer := TTimer.Create(nil);     with FTimer do     begin         Interval := 1000;         OnTimer := self.DoTimer;         Enabled := True;     end; end; destructor TClockTimer.Destroy; begin     FTimer.Free;     //---     inherited; end; function TClockTimer.GetHour(): integer; begin     Result := HourOf(FTime); end; function TClockTimer.GetMinute: integer; begin     Result := MinuteOf(FTime); end; function TClockTimer.GetSecond: integer; begin     Result := SecondOf(FTime); end; procedure TClockTimer.Tick(); begin     FTime := Now;     //---     self.Notify(); end; procedure TClockTimer.DoTimer(Sender: TObject); begin     self.Tick; end; constructor TDigitClock.Create(AOwner: TComponent; const ASubject: TClockTimer); begin     inherited Create(AOwner);     //---     FSubject := ASubject;     FSubject.Attach(self); end; destructor TDigitClock.Destroy; begin     FSubject.Detach(self);     //---     inherited; end; procedure TDigitClock.IUpdate(theChangedSubject: TSubject); begin     if theChangedSubject = FSubject then         self.Draw(); end; procedure TDigitClock.Draw(); var     AText: string;     AHour, AMinute, ASecond: Integer; begin     with FSubject do     begin         AHour := GetHour();         AMinute := GetMinute();         ASecond := GetSecond();     end;     AText := Format('%d:%d:%d', [AHour, AMinute, ASecond]);     //---     with self.Canvas do     begin         with Brush do         begin             Color := clBlack;             Style := bsSolid;         end;         FillRect(self.ClientRect);         //---         with Font do         begin             Color := clRed;             Size := 10;         end;         with TextExtent(AText) do             TextOut((Self.Width - cX) div 2, (self.Height - cY) div 2, AText);     end; end; procedure TWidget.Paint; begin     self.Draw; end; constructor TAnalogClock.Create(AOwner: TComponent; const ASubject:     TClockTimer); begin     inherited Create(AOwner);     //---     FSubject := ASubject;     FSubject.Attach(self); end; destructor TAnalogClock.Destroy; begin     FSubject.Detach(self);     //---     inherited; end; procedure TAnalogClock.Draw; var     AText: string;     AHour, AMinute, ASecond: Integer; begin     with FSubject do     begin         AHour := GetHour();         AMinute := GetMinute();         ASecond := GetSecond();     end;     AText := Format('%d:%d:%d', [AHour, AMinute, ASecond]);     //---     with self.Canvas do     begin         with Brush do         begin             Color := clBlack;             Style := bsSolid;         end;         FillRect(self.ClientRect);         //---         with Font do         begin             Color := clYellow;             Size := 10;         end;         with TextExtent(AText) do             TextOut((Self.Width - cX) div 2, (self.Height - cY) div 2, AText);     end; end; procedure TAnalogClock.IUpdate(theChangedSubject: TSubject); begin     if theChangedSubject = FSubject then         self.Draw(); end; end. 测试 unit Unit1; interface uses     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,     Dialogs, uClock, ExtCtrls; type     TForm1 = class(TForm)         procedure FormDestroy(Sender: TObject);         procedure FormCreate(Sender: TObject);     private         FTimer: TClockTimer;         FDigitClock: TDigitClock;         FAnalogClock: TAnalogClock;     public     { Public declarations }     end; var     Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin     FTimer := TClockTimer.Create;     //---     FDigitClock := TDigitClock.Create(nil, FTimer);     with FDigitClock do     begin         Parent := Self;         Top := 10;         Left := 10;         Width := 100;         Height := 30;     end;     //---     FAnalogClock := TAnalogClock.Create(nil, FTimer);     with FAnalogClock do     begin         Parent := Self;         Top := 60;         Left := 10;         Width := 100;         Height := 30;     end; end; procedure TForm1.FormDestroy(Sender: TObject); begin     FAnalogClock.Free;     FDigitClock.Free;     FTimer.Free; end; end.


    最新回复(0)