示例:显式地指定感兴趣的改变
说明:
你可以扩展目标的注册接口,让各观察者注册为仅对特定事件感兴趣,以提高更新的效率。当一个事件发生时,目标仅通知那些已注册为对该事件感兴趣的观察者。
代码:
unit uAspects;
interface
uses
SysUtils, Classes, Dialogs;
type
TAspect = (apCalcEvent1,apCalcEvent2);
TObserver = class;
RMapInfo = record
Interest:TAspect;
Observer: TObserver;
end;
PMapInfo = ^RMapInfo;
TMapList = class(TList)
private
function GetItems(Index: Integer): PMapInfo;
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
public
function Add(AInterest: TAspect; AObserver: TObserver): Integer;
function IndexOf(AInterest: TAspect; AObserver: TObserver): Integer;
procedure Delete(AInterest: TAspect; AObserver: TObserver);
//---
property Items[Index: Integer]: PMapInfo read GetItems;
end;
TSubject = class
private
FObservers: TMapList;
FInterest:TAspect;
public
constructor Create;
destructor Destroy; override;
//---
procedure Attach(AObserver: TObserver;AInterest:TAspect);
procedure Detach(AObserver: TObserver;AInterest:TAspect);
procedure Notify;
end;
TConcreteSubject = class(TSubject)
private
FState: Integer;
public
procedure Calc1;
procedure Calc2;
//---
property State: Integer read FState;
end;
TObserver = class
public
procedure Update(ASubject: TSubject;AInterest:TAspect); virtual; abstract;
end;
TConcreteObserver = class(TObserver)
public
procedure Update(ASubject: TSubject;AInterest:TAspect); override;
end;
procedure Test;
implementation
procedure Test;
var
ASubject: TConcreteSubject;
AObserver: TObserver;
begin
ASubject := TConcreteSubject.Create;
AObserver := TConcreteObserver.Create;
try
ASubject.Attach(AObserver,apCalcEvent2);
ASubject.Calc1;
ASubject.Calc2;
finally
AObserver.Free;
ASubject.Free;
end;
end;
constructor TSubject.Create;
begin
FObservers := TMapList.Create;
end;
destructor TSubject.Destroy;
begin
FObservers.Free;
//---
inherited;
end;
procedure TSubject.Attach(AObserver: TObserver;AInterest:TAspect);
begin
FObservers.Add(AInterest,AObserver);
end;
procedure TSubject.Detach(AObserver: TObserver;AInterest:TAspect);
begin
FObservers.Delete(AInterest,AObserver);
end;
procedure TSubject.Notify;
var
i: integer;
begin
with FObservers do
begin
for i := 0 to Count - 1 do
begin
with Items[i]^ do
begin
if Interest = FInterest then
Observer.Update(self,Interest);
end;
end;
end;
end;
procedure TConcreteObserver.Update(ASubject: TSubject;AInterest:TAspect);
begin
if ASubject is TConcreteSubject then
begin
with TConcreteSubject(ASubject) do
ShowMessage(IntToStr(State));
end;
end;
function TMapList.Add(AInterest: TAspect; AObserver: TObserver): Integer;
var
pData: PMapInfo;
begin
New(pData);
pData.Interest := AInterest;
pData.Observer := AObserver;
//---
Result := inherited Add(pData);
end;
procedure TMapList.Delete(AInterest: TAspect; AObserver: TObserver);
var
AIndex:Integer;
begin
AIndex := IndexOf(AInterest, AObserver);
if AIndex >= 0 then
inherited Delete(AIndex);
end;
function TMapList.GetItems(Index: Integer): PMapInfo;
begin
Result := inherited Items[Index];
end;
function TMapList.IndexOf(AInterest: TAspect; AObserver: TObserver): Integer;
var
i:Integer;
begin
for i := 0 to self.Count - 1 do
begin
with Self.Items[i]^ do
if (Interest = AInterest) and (Observer = AObserver) then
begin
Result := i;
Exit;
end;
end;
//---
Result := -1;
end;
procedure TMapList.Notify(Ptr: Pointer; Action: TListNotification);
begin
if Action = lnDeleted then
Dispose(Ptr);
//---
inherited;
end;
procedure TConcreteSubject.Calc1;
begin
FInterest := apCalcEvent1;
FState := FState + 1;
//---
Self.Notify;
end;
procedure TConcreteSubject.Calc2;
begin
FInterest := apCalcEvent2;
FState := FState * 2;
//---
Self.Notify;
end;
end.
《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:显式地指定感兴趣的改变
最新推荐文章于 2024-09-19 20:16:02 发布