Полный пример - запросто.
Я пытаюсь сделать реализацию шаблона Publisher - Subscriber. Готовые реализации в количестве 1 штуки для Delphi видел краем глаза, и она мне не понравилась.
Подписчик:
Код: Выделить всё
{$OBJECTCHECKS ON}
{$INTERFACES CORBA}
interface
uses Classes, SysUtils, Forms;
type
{ ISubscriber }
ISubscriber = interface
['{7B3C558B-00BE-424D-91AC-5F9D894CC51B}']
procedure Notify(AEvent: string);
end;
{ TSubscriber }
TSubscriber = class (TForm, ISubscriber) // TForm взят с потолка, можно подставить любой другой класс по вкусу...
public
procedure Notify(AEvent: string); virtual;
end;
implementation
{ TSubscriber }
procedure TSubscriber.Notify(AEvent: string);
begin
end;
Publisher:
Код: Выделить всё
uses
Classes, SysUtils, Subscriber;
type
{ TPublisher }
TPublisher = class
private
FList: TStringList;
public
constructor Create;
destructor Destroy; override;
function SubscriptionIndex(ASubscriber: TSubscriber; AEvent: string): longint;
procedure Subscribe(ASubscriber: TSubscriber; AEvent: string); virtual;
procedure Unsubscribe(ASubscriber: TSubscriber; AEvent: string); virtual;
procedure Notify(AEvent: string); virtual;
end;
implementation
procedure TPublisher.Notify(AEvent: string);
{ Уведомляет всех подписчиков на событие AEvent о том, что оно случилось. }
var i: longint;
begin
for i:=0 to FList.Count-1 do
if AEvent=FList.Strings[i] then
(FList.Objects[i] as ISubscriber).Notify(AEvent); // Ошибка тут
end;
Общий принцип работы
Publisher'a: подписчики подписываются на определенные события (название события хранятся как строки). В Publisher'e есть список TStringList, который хранит набор строк и связанных с ними объектов. Таким образом каждый объект может подписаться на несколько разных событий и получить информацию о том, какое именно случилось. Остальные методы не привожу, чтобы не загромождать текст.
Вот код тестирующей процедуры:
Код: Выделить всё
procedure TPublisherTestCase.NotifyTest;
var event: string;
s1, s2, s3: TTestSubscriber;
begin
s1:=TTestSubscriber.Create(nil);
s2:=TTestSubscriber.Create(nil);
s3:=TTestSubscriber.Create(nil);
p.Subscribe(s1, 'event1');
p.Subscribe(s2, 'event2');
p.Subscribe(s3, 'event3');
p.Subscribe(s2, 'event4');
p.Notify('event2');
AssertEquals('Subscriber was not notified', 'event2', s2.NotifyRecieved);
FreeAndNil(s1);
FreeAndNil(s2);
FreeAndNil(s3);
end;
Во вложении - проект для fpcunit, там полные тексты обоих модулей и тесткейс для тестирования класса.
Добавлено спустя 5 минут 29 секунд:P. S. TTestSubscriber - потомок TSubscriber, но сути проблемы это не меняет.