一个观察者模式的疑问,模式高手请赐教!!!!(100分)

  • 主题发起人 主题发起人 cdmwz
  • 开始时间 开始时间
C

cdmwz

Unregistered / Unconfirmed
GUEST, unregistred user!
代码如下:
声明---------------------
IObserver = interface(IInterface)
procedure Update;
end;

TConcreteObserver = class(TInterfacedObject,IObserver)
public
procedure Update;
end;

TConcreteObserver1 = class(TInterfacedObject,IObserver)
public
procedure Update;
end;

TConcreteObserver2 = class(TInterfacedObject,IObserver)
public
procedure Update;
end;

TAbstractSubject = class
protected
FObservers: TList;
public
procedure Attach(AObserver: IObserver)
virtual
abstract;
procedure Detach(AObserver: IObserver)
virtual
abstract;
procedure NotifyObservers
virtual
abstract;
end;

TConcreteSubject = class(TAbstractSubject)
public
procedure Attach(AObserver: IObserver)
override;
procedure Detach(AObserver: IObserver)
override;
procedure NotifyObservers
override;
constructor Create;
destructor Destroy
override;
end;
实现---------------------
{ TConcreteSubject }

procedure TConcreteSubject.Attach(AObserver: IObserver);
begin
inherited;
FObservers.Add(@AObserver);
end;

constructor TConcreteSubject.Create;
begin
FObservers := TList.Create;
end;

destructor TConcreteSubject.Destroy;
begin
FreeAndNil(FObservers);
inherited;
end;

procedure TConcreteSubject.Detach(AObserver: IObserver);
begin
inherited;
FObservers.Remove(@AObserver);
end;

procedure TConcreteSubject.NotifyObservers;
var
I: Integer;
begin
inherited;
for I:=0 to FObservers.Count - 1 do
{用这句代码有问题}
//IObserver(FObservers.Items).Update;

{用这句代码没问题,但是不能实现多态}
TConcreteObserver(FObservers.Items).Update;
end;

{ TContreteObserver }

procedure TConcreteObserver.Update;
begin
ShowMessage('TConcreteObserver called');
end;

{ TConcreteObserver1 }

procedure TConcreteObserver1.Update;
begin
ShowMessage('TConcreteObserver1 called');
end;

{ TConcreteObserver2 }

procedure TConcreteObserver2.Update;
begin
ShowMessage('TConcreteObserver2 called');
end;
调用---------
procedure TfmMain.Button3Click(Sender: TObject);
begin
ASubject := TConcreteSubject.Create;
Observer1 := TConcreteObserver.Create;
Observer2 := TConcreteObserver.Create;
Observer3 := TConcreteObserver.Create;
Observer11 := TConcreteObserver1.Create;
Observer12 := TConcreteObserver1.Create;
Observer13 := TConcreteObserver1.Create;
Observer21 := TConcreteObserver2.Create;
Observer22 := TConcreteObserver2.Create;
Observer23 := TConcreteObserver2.Create;

ASubject.Attach(Observer1);
ASubject.Attach(Observer2);
ASubject.Attach(Observer3);
ASubject.Attach(Observer11);
ASubject.Attach(Observer12);
ASubject.Attach(Observer13);
ASubject.Attach(Observer21);
ASubject.Attach(Observer22);
ASubject.Attach(Observer23);
end;

procedure TfmMain.Button5Click(Sender: TObject);
begin
ASubject.NotifyObservers;
end;

procedure TfmMain.Button4Click(Sender: TObject);
begin
ASubject.Detach(Observer1);
ASubject.Detach(Observer2);
ASubject.Detach(Observer3);
ASubject.Detach(Observer11);
ASubject.Detach(Observer12);
ASubject.Detach(Observer13);
ASubject.Detach(Observer21);
ASubject.Detach(Observer22);
ASubject.Detach(Observer23);

Observer1.Free;
Observer2.Free;
Observer3.Free;
Observer11.Free;
Observer12.Free;
Observer13.Free;
Observer21.Free;
Observer22.Free;
Observer23.Free;
ASubject.Free;
end;
我的问题在TConcreteSubject.NotifyObservers方法,如果我用接口调用,肯定会错,但如果用具体实现接口的类来调用,则不能实现多态,请问哪里出了问题?
我的要求是:一个具体的被观察者,要求被不同类的对象观察,当被观察者发生改变,所有不同类型的对象都要被通知到。
请高手赐教!
 
这么快就沉了?顶上去!
 
这是因为你的接口在调用后被释放了,建议重写那三个基本的接品方法,并不产生释放操作就可以了
 
TConcreteSubject = class(TAbstractSubject)
public
procedure Attach(const AObserver: IObserver)
override
//const 避免接口自动动作
procedure Detach(const AObserver: IObserver)
override
//
procedure NotifyObservers
override;
constructor Create;
destructor Destroy
override;
end;


procedure TConcreteSubject.Attach(const AObserver: IObserver);
begin
inherited;
FObservers.Add(Pointer(AObserver));
end;

procedure TConcreteSubject.Detach(const AObserver: IObserver);
begin
inherited;
FObservers.Remove(Pointer(AObserver));
end;

procedure TConcreteSubject.NotifyObservers;
var
I: Integer;
begin
inherited;
for I:=0 to FObservers.Count - 1 do
IObserver(FObservers.Items).Update;
end;
 
to chinaxuguojun:
您误解我的意思了,我是在Free之前就报的AV异常,不过还是感谢您的关注!

to jeffrey_s:
您结决了我的问题,非常感谢您。
 
接受答案了.
 
后退
顶部