已经找到解决方案:) 问题就出在 Delphi 会自动管理接口的生命周期,于是,
你在保存该接口的引用的时候应该人为地增加其引用计数:
unit TestUnit;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
IObserver = interface(IInterface)
procedure Update(const Msg: string);
end;
TBookObserver = class(TInterfacedObject, IObserver)
public
procedure Update(const Msg: string);
destructor Destroy
override;
end;
TNewspaperObserver = class(TInterfacedObject, IObserver)
public
procedure Update(const Msg: string);
destructor Destroy
override;
end;
TfrmMain = class(TForm)
btnRegObserver: TButton;
btnNotifyHello: TButton;
btnNotifyWorld: TButton;
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject
var Action: TCloseAction);
procedure btnRegObserverClick(Sender: TObject);
procedure btnNotifyHelloClick(Sender: TObject);
procedure btnNotifyWorldClick(Sender: TObject);
private
FList: TList;
protected
procedure Notify(const Msg: string);
public
procedure RegisterObserver(Observer: IObserver);
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
{ TObserver1 }
destructor TBookObserver.Destroy;
begin
ShowMessage('Book Observer Destroyed');
inherited;
end;
procedure TBookObserver.Update(const Msg: string);
begin
ShowMessage(Format('BookObserver updated: [%s]', [Msg]));
end;
{ TObserver2 }
destructor TNewspaperObserver.Destroy;
begin
ShowMessage('Newspaper Observer Destroyed');
inherited;
end;
procedure TNewspaperObserver.Update(const Msg: string);
begin
ShowMessage(Format('TNewspaperObserver updated: [%s]', [Msg]));
end;
{ TfrmMain }
procedure TfrmMain.FormCreate(Sender: TObject);
begin
FList := TList.Create;
end;
procedure TfrmMain.FormClose(Sender: TObject
var Action: TCloseAction);
begin
FList.Free;
end;
procedure TfrmMain.RegisterObserver(Observer: IObserver);
begin
Observer._AddRef
// [red]关键就在这一句![/red]
FList.Add(Pointer(Observer));
end;
procedure TfrmMain.Notify(const Msg: string);
var
Index: Integer;
begin
for Index := 0 to FList.Count - 1 do
begin
IObserver(FList[Index]).Update(Msg);
end;
end;
procedure TfrmMain.btnRegObserverClick(Sender: TObject);
begin
RegisterObserver(TBookObserver.Create);
RegisterObserver(TNewspaperObserver.Create);
RegisterObserver(TNewspaperObserver.Create);
RegisterObserver(TBookObserver.Create);
end;
procedure TfrmMain.btnNotifyHelloClick(Sender: TObject);
begin
Notify('Hello');
end;
procedure TfrmMain.btnNotifyWorldClick(Sender: TObject);
begin
Notify('World');
end;
end.
完整示例源代码(含可执行程序共171K)可在这里下载:
http://www.01cn.net/cgi-bin/topic_show.cgi?id=1109&pg=1&age=0&bpg=1