示例:时钟
说明:
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.
《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:时钟
最新推荐文章于 2024-04-25 10:49:29 发布