《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:显式地指定感兴趣的改变
2011-03-03 10:09
615 查看
示例:显式地指定感兴趣的改变
说明:
你可以扩展目标的注册接口,让各观察者注册为仅对特定事件感兴趣,以提高更新的效率。当一个事件发生时,目标仅通知那些已注册为对该事件感兴趣的观察者。
代码:
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.
说明:
你可以扩展目标的注册接口,让各观察者注册为仅对特定事件感兴趣,以提高更新的效率。当一个事件发生时,目标仅通知那些已注册为对该事件感兴趣的观察者。
代码:
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源码示例:推模型(push model)
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:拉模型(pull model)
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:封装复杂的更新语义
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:时钟
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:观察者接口
- 《GOF设计模式》—观察者(OBSERVER)—Delphi源码示例:图形用户界面工具箱
- 《GOF设计模式》—中介者 (MEDIATOR)—Delphi源码示例:Colleague—Mediator通信(使用观察者模式)
- 《GOF设计模式》—组合(COMPOSITE)—Delphi源码示例:显式的父部件引用
- 《GOF设计模式》—命令(COMMAND)—Delphi源码示例:在不同的时刻指定、排列和执行请求
- 《GOF设计模式》—装饰(DECORATOR)—Delphi源码示例:改变对象内核
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:乐谱编辑器
- 《GOF设计模式》—迭代器 (ITERATOR)—Delphi源码示例:用于复合对象的内部迭代器
- 《GOF设计模式》—原型(Prototype)—Delphi源码示例:初始化克隆对象
- 《GOF设计模式》—模板方法(TEMPLATE METHOD)—Delphi源码示例:绘图
- 《GOF设计模式》—桥接(BRIDGE)—Delphi源码示例:可移植的用户界面
- 《GOF设计模式》—桥接(BRIDGE)—Delphi源码示例:创建正确的Implementor对象(缺省的实现)
- 《GOF设计模式》—代理(PROXY)—Delphi源码示例:文档编辑器(使用虚代理实现)
- 《GOF设计模式》—工厂方法(Factory Method)—Delphi源码示例:为子类提供挂钩(hook)
- 《GOF设计模式》—生成器(Builder)—Delphi源码示例:RTF阅读器