用Delphi实现四人帮(Gof)设计模式-9观察者模式Publish/Subscribe,Observer - cococlout的专栏 - CSDN博客

来源:百度文库 编辑:神马文学网 时间:2024/04/28 10:28:15

用Delphi实现四人帮(Gof)设计模式-9观察者模式Publish/Subscribe,Observer收藏

观察者模式又叫发布-订阅模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.这个主题对象在状态变化时会通知所有观察者对象,使他们能够更新自己.在设计软件系统时将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相关对象之间的一致性,我们当然不希望为了维护一致性而使得各个类之间紧密耦合,紧密耦合会给维护,扩展和重用都带来不便.而观察者模式的关键对象是主题Subject和观察者,一个主题可以有任意数目的观察者依赖于它,一旦主题的状态发生了改变,所有的观察者都可以得到通知,而主题在发出通知时根本不知道谁是他的观察者,也不需要知道,对任何一个观察者,也不需要知道其它观察者的存在.

当一个对象的改变需要同时改变其它对象,而且不知道具体有多少对象改变的时候,我们就需要使用观察者模式了.观察者模式所做的工作其实就是在解除耦合,让耦合的双方都依赖于抽象,而不是依赖于具体.从而使得各自的变化都不会影响另一边的变化,这也是依赖倒转原则的体现.

观察者可能是风马牛不相及的类,但它们都需要根据通知者的通知来做出Update操作.

观察者模式的类图如下:

 

 

下面通过接口实现观察者模式,本人目前对接口的机制还不能很好的掌握,程序虽然能够编译执行,但可能存在实现不良好之处,请看客们指教一二.

  1. {************************************************** 

  2.   实现Observer          

  3.   UnitOwner:coco.zhang                            
  4.   Last Modified:2008-10-5                    
  5.  **************************************************}
  6. unit ObserverUnit;
  7. interface
  8. uses
  9.     Windows,classes;
  10. type   
  11.   // TSubject = class; //类的相互依赖声明
  12.   {观察者接口}
  13.   IObserver = interface
  14.       procedure Update(ASubject : TObject);stdcall;//通过TObject传入Subject对象,就不用相互依赖声明了
  15.   end;
  16.   PointerTOObserver = ^IObserver;
  17.   {观察者类}
  18.   TConcreteObserver = class(TInterfacedObject, IObserver)
  19.      MName : string;
  20.   public
  21.       constructor Create(Name : string);
  22.       {使用观察者模式,需要具体的观察者必须重载此方法,以实现主题变化后,观察者状态的更新情况}
  23.       procedure Update(ASubject : TObject);stdcall; //注意参数为TObject, 可以造型为具体的主题对象
  24.   end;

  25.    {主题类}
  26.   TSubject = class(TObject)
  27.      protected 
  28.           State : string;
  29.       AContainer : TList; 
  30.      public
  31.           constructor Create;
  32.    {注意,这里使用了指针,直接使用接口是不行的,传引用也不行,也许我还没有搞清楚接口机制}
  33.           procedure Attach(AnObserver: PointerTOObserver );virtual;
  34.       procedure  Notify();virtual;
  35.       function GetState():string;virtual;abstract;
  36.   end;
  37.  {具体的主题类,添加了触发方法,此方法也可在父类中声明为抽象方法}
  38.   TConcreteSubject = class(TSubject)
  39.      public
  40.          procedure ChangeState(AState : string);  
  41.      function    GetState():string;override;  //可以父类实现,去掉也可,结合具体应用调整之
  42.   end;

  43. {----------------------------------}  
  44. implementation
  45. {抽象主题类实现}
  46.  constructor TSubject.Create;
  47.  begin
  48.    AContainer := TList.Create;
  49.  end;
  50. procedure TSubject.Attach(AnObserver: PointerTOObserver );
  51.  begin
  52.      AContainer.Add(AnObserver);
  53.  end;
  54. procedure TSubject.Notify;
  55. var 
  56.   I : Integer;
  57.   PObserver : PointerTOObserver;
  58. begin
  59.     for I := 0 to AContainer.Count - 1 do
  60.     begin       
  61.         PObserver := AContainer.Items[I];   
  62.         PObserver^.Update(self); //引发异常
  63.     end;
  64. end;
  65. {具体观察者实现}
  66. constructor TConcreteObserver.Create(Name : string);
  67. begin
  68.    self.MName := Name;
  69. end;
  70. procedure TConcreteObserver.Update(ASubject : TObject);stdcall;
  71. begin
  72.    Writeln( TSubject(ASubject).GetState());
  73. end;
  74. {具体主题实现}
  75. procedure TConcreteSubject.ChangeState(AState : string);  
  76. begin
  77.     State := AState;
  78.     Notify();
  79. end;
  80. function TConcreteSubject.GetState(): string;  
  81. begin
  82.     Result := State;
  83. end;
  84. end.

客户端

  1. program Observer;
  2. {$APPTYPE CONSOLE}
  3. uses 
  4.  classes,ObserverUnit;
  5.  var
  6.    AObserver : TConcreteObserver;
  7.    ASubject : TConcreteSubject;
  8.    AVar : IObserver;
  9.  begin
  10.    ASubject := TConcreteSubject.Create;
  11.    AObserver := TConcreteObserver.Create('A');   
  12.    AVar := IObserver(AObserver); //非要转一次吗,啰嗦
  13.    ASubject.Attach(@AVar);
  14.    ASubject.ChangeState('The State of Subject Changed!');
  15.  end.

执行结果:


D:\Projects\Delphi7\src\GofProjects\Observer> observer
The State of Subject Changed!

下面用抽象类实现观察者模式

  1. {************************************************** 

  2.   实现Observer   用抽象类实现观察者      

  3.   UnitOwner:coco.zhang                            
  4.   Last Modified:2008-10-5                    
  5.  **************************************************}
  6. unit ObserverUnit;
  7. interface
  8. uses
  9.     Windows,classes;
  10. type   
  11.   // TSubject = class; //类的相互依赖声明
  12.   {观察者接口}
  13.   TObserver = class
  14.       procedure Update(ASubject : TObject);virtual;abstract;
  15.   end;
  16.    {观察者类}
  17.   TConcreteObserver = class(TObserver)
  18.   protected
  19.      MName : string;
  20.   public
  21.       constructor Create(Name : string);
  22.        procedure Update(ASubject : TObject);override;  
  23.   end;

  24.    {主题类}
  25.   TSubject = class(TObject)
  26.      protected 
  27.           State : string;
  28.       AContainer : TList; 
  29.      public
  30.           constructor Create;
  31.            procedure Attach(AnObserver : TObserver );virtual;
  32.       procedure  Notify();virtual;
  33.       function GetState():string;virtual;abstract;
  34.   end;
  35.  {具体的主题类,添加了触发方法,此方法也可在父类中声明为抽象方法}
  36.   TConcreteSubject = class(TSubject)
  37.      public
  38.          procedure ChangeState(AState : string);  
  39.      function    GetState():string;override;  //可以父类实现,去掉也可,结合具体应用调整之
  40.   end;

  41. {----------------------------------}  
  42. implementation
  43. {抽象主题类实现}
  44.  constructor TSubject.Create;
  45.  begin
  46.    AContainer := TList.Create;
  47.  end;
  48. procedure TSubject.Attach(AnObserver: TObserver );
  49.  begin
  50.      AContainer.Add(AnObserver);
  51.  end;
  52. procedure TSubject.Notify;
  53. var 
  54.   I : Integer;
  55.   PObserver : TObserver;
  56. begin
  57.     for I := 0 to AContainer.Count - 1 do
  58.     begin       
  59.         PObserver := AContainer.Items[I];   
  60.         PObserver.Update(self); //引发异常
  61.     end;
  62. end;
  63. {具体观察者实现}
  64. constructor TConcreteObserver.Create(Name : string);
  65. begin
  66.    self.MName := Name;
  67. end;
  68. procedure TConcreteObserver.Update(ASubject : TObject);
  69. begin
  70.    Writeln('Name of Observer:' + MName + ' State of Subject :'+TSubject(ASubject).GetState());
  71. end;
  72. {具体主题实现}
  73. procedure TConcreteSubject.ChangeState(AState : string);  
  74. begin
  75.     State := AState;
  76.     Notify();
  77. end;
  78. function TConcreteSubject.GetState(): string;  
  79. begin
  80.     Result :=  State;
  81. end;
  82. end.

客户端

 

  1. program Observer;
  2. {$APPTYPE CONSOLE}
  3. uses 
  4.  classes,ObserverUnit;
  5.  var
  6.    ASubject : TConcreteSubject;
  7.   begin
  8.    ASubject := TConcreteSubject.Create;
  9.    ASubject.Attach(TConcreteObserver.Create('A'));
  10.    ASubject.ChangeState('NewState');
  11.  end.

执行结果

D:\Projects\Delphi7\src\GofProjects\Observer> observer
Name of Observer:A State of Subject :NewState