由于Delphi不支持多重继承,在实现Observer模式的时候,TObserver就只能从TComponent或者从某个具体的可视控件(例如TStringGrid)继承下来。这样的问题是,如果从TComponent继承下来,可以复用会更方便些,可是,这也意味着需要自己重新写用于显示的控件;如果直接从某个具体的控件继承下来,那样复用又会受到影响,对于每一个风格的控件,需要不同的父控件。
如果使用接口来模拟多重继承来解决上面的问题,在实现的时候,总是有些问题,甚至很不好弄。请求哪位达人指点一下如何实现。

解决方案 »

  1.   

    看你的描述,感觉你比较适合使用桥接(Bridge)模式,将抽象化与实现化脱藕,使得二者可以独立的变化.
      

  2.   

    如果你也在用Java,可以模拟一下Java中的Listener/Event,它也是观察者模式,Java也是只有接口而无多重继承。
    可以很肯定地说,必须使用接口。
      

  3.   

    看了一晚上本社区的帖子,还是回答一下问题吧。
    ////
    由于Delphi不支持多重继承,在实现Observer模式的时候,TObserver就只能从TComponent或者从某个具体的可视控件(例如TStringGrid)继承下来。这样的问题是,如果从TComponent继承下来,可以复用会更方便些,可是,这也意味着需要自己重新写用于显示的控件;如果直接从某个具体的控件继承下来,那样复用又会受到影响,对于每一个风格的控件,需要不同的父控件。
    如果使用接口来模拟多重继承来解决上面的问题,在实现的时候,总是有些问题,甚至很不好弄。请求哪位达人指点一下如何实现。
    ////
    您的以上感觉我不知道是从何来的?给我的感觉是您不仅仅对模式没有概念,对OO也没有一点概念(请包涵我的措辞)。不过还是就事论事各您一个完整的答案。unit Pattern.SubjectIntf;interfaceuses
      Pattern.ObserverIntf;type
      ISubject = interface
      ['{13BF13FC-09A5-4321-888C-9A29BD0AE893}']
        procedure Attach(const Observer: IObserver);
        procedure Detach(const Observer: IObserver);
        procedure BeginUpdate;
        procedure EndUpdate;
        procedure Notify;
      end;implementationend.unit Pattern.ObserverIntf;interfacetype
      IObserver = interface
      ['{D8BC1C6F-074A-40F6-AD00-05A16159C26C}']
        procedure Update(const Subject: IInterface);
      end;implementationend.unit Pattern.SubjectImpl;interfaceuses
      Classes, Pattern.SubjectIntf, Pattern.ObserverIntf;type
      TSubject = class(TInterfacedObject, ISubject)
      private
        FObservers: IInterfaceList;
        FController: Pointer;
        FUpdateCount: Integer;
        function GetController: IInterface;
      protected
        //ISubject
        procedure Attach(const Observer: IObserver);
        procedure Detach(const Observer: IObserver);
        procedure BeginUpdate;
        procedure EndUpdate;
        procedure Notify;
      public
        constructor Create(const Controller: IInterface); virtual;
        destructor Destroy; override;
      end;implementation{ TSubject }procedure TSubject.Attach(const Observer: IObserver);
    begin
      if FObservers = nil then
        FObservers := TInterfaceList.Create;
      if FObservers.IndexOf(Observer) < 0 then
        FObservers.Add(Observer);
    end;procedure TSubject.BeginUpdate;
    begin
      Inc(FUpdateCount);
    end;constructor TSubject.Create(const Controller: IInterface);
    begin
      inherited Create;
      FController := Pointer(Controller);
      FUpdateCount := 0;
    end;destructor TSubject.Destroy;
    begin
      inherited;
    end;procedure TSubject.Detach(const Observer: IObserver);
    begin
      if FObservers <> nil then
      begin
        if FObservers.IndexOf(Observer) >= 0 then
        begin
          FObservers.Remove(Observer);
          if FObservers.Count = 0 then
            FObservers := nil;
        end;
      end;
    end;procedure TSubject.EndUpdate;
    begin
      Dec(FUpdateCount);
      if FUpdateCount = 0 then
        Notify;
    end;function TSubject.GetController: IInterface;
    begin
      Result := IInterface(FController);
    end;procedure TSubject.Notify;
    var
      Idx: Integer;
    begin
      if FObservers <> nil then
        for Idx := 0 to Pred(FObservers.Count) do
          if FObservers[Idx] <> nil then
            (FObservers[Idx] as IObserver).Update(GetController);
    end;end.unit  Frame.BizWindowsObserverFrame;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, Pattern.ObserverIntf;
    type
      TBizWindowsObserverFrame = class(TFrame, IObserver)
      private
        //IObserver
        procedure IObserver.Update = ObserverUpdate;
        procedure ObserverUpdate(const Subject: IInterface);
        procedure ObserverRegister;
        procedure ObserverUnRegister;
      protected
      public
      end;
    ...................
      

  4.   

    PS: 至于TFrame只是我的例子而已,您可以任意改变