Page 1 of 1

Subscriber/Observer Pattern

Posted: Wed Sep 03, 2025 9:28 pm
by Phollyer
I'm sure this is child's play for most of you...I was board so I implemented the Subscriber pattern in Modules...

Code: Select all

DeclareModule  SUBSCRIBER
  Structure Subscriber
    ID.i
    Name.s
  EndStructure
  Declare Update(*ToWhom.SUBSCRIBER::Subscriber, News.s)
EndDeclareModule

Module SUBSCRIBER
  Procedure Update(*ToWhom.SUBSCRIBER::Subscriber, News.s)
    MessageRequester("NEWS Broadcast to "+ *ToWhom\Name, News, #PB_MessageRequester_Info)
  EndProcedure
EndModule



DeclareModule PUBLISHER
  
  Structure Publisher
    News.s
    List Subscribers.SUBSCRIBER::Subscriber()
  EndStructure
  
  Declare AddObserver(*Observer.SUBSCRIBER::Subscriber, *Publisher.PUBLISHER::Publisher)
  Declare RemoveObsererver(*Observer.SUBSCRIBER::Subscriber, *Publisher.PUBLISHER::Publisher)
  
  Declare NotifyObservers(*Publisher.PUBLISHER::Publisher)
  Declare SetNews(News.s, *Publisher.PUBLISHER::Publisher)
  Declare UpdateDailyNews(*Publisher.PUBLISHER::Publisher)
  
EndDeclareModule

Module PUBLISHER
  Procedure AddObserver(*Observer.SUBSCRIBER::Subscriber, *Publisher.PUBLISHER::Publisher)
    AddElement(*Publisher\Subscribers())
    *Publisher\Subscribers()\ID = *Observer\ID
    *Publisher\Subscribers()\Name = *Observer\Name
  EndProcedure
  
  Procedure RemoveObsererver(*Observer.SUBSCRIBER::Subscriber, *Publisher.PUBLISHER::Publisher)
    Protected X
    For X = ListSize(*Publisher\Subscribers())-1 To 0 Step -1
      SelectElement(*Publisher\Subscribers(), X)
      If *Publisher\Subscribers()\ID = *Observer\ID And
         *Publisher\Subscribers()\Name = *Observer\Name
        DeleteElement(*Publisher\Subscribers())
        Break
      EndIf
    Next
  EndProcedure
  
  Procedure NotifyObservers(*Publisher.PUBLISHER::Publisher)
    Protected X
    For X = ListSize(*Publisher\Subscribers())-1 To 0 Step -1
      SelectElement(*Publisher\Subscribers(), X)
      SUBSCRIBER::Update(*Publisher\Subscribers(), *Publisher\News)
    Next
  EndProcedure
  
  Procedure SetNews(News.s, *Publisher.PUBLISHER::Publisher)
    *Publisher\News = News
  EndProcedure
  
  Procedure UpdateDailyNews(*Publisher.PUBLISHER::Publisher)
    PUBLISHER::NotifyObservers(*Publisher)
  EndProcedure
  
EndModule



MSNBC.PUBLISHER::Publisher

George.SUBSCRIBER::Subscriber
George\ID = 1
George\Name ="George"

PUBLISHER::AddObserver(@George, @MSNBC)

Martha.SUBSCRIBER::Subscriber
Martha\ID = 1
Martha\Name ="Martha"

PUBLISHER::AddObserver(@Martha, @MSNBC)

PUBLISHER::SetNews("Breaking NEWS...Nothing Happened!", @MSNBC)
PUBLISHER::UpdateDailyNews(@MSNBC)



Re: Subscriber/Observer Pattern

Posted: Thu Sep 04, 2025 11:33 am
by Little John
Hi, some remarks.

Since this is in the “Tricks 'n' Tips” section of the forum, it wouldbe good if the code is as educational and straightforward as possible.
In the above procedure RemoveObsererver(), there is no need to use an index variable together with SelectElement(). And SelectElement() is rather slow. This is better:

Code: Select all

  Procedure RemoveObsererver(*Observer.SUBSCRIBER::Subscriber, *Publisher.PUBLISHER::Publisher)
     ForEach *Publisher\Subscribers()
        If *Publisher\Subscribers()\ID = *Observer\ID And
           *Publisher\Subscribers()\Name = *Observer\Name
           DeleteElement(*Publisher\Subscribers())
           Break
        EndIf
     Next
  EndProcedure
The same applies to procedure NotifyObservers().
 
 
George\ID = 1
[...]
Martha\ID = 1
An ID must be unique. Assignment (and reuse) of IDs should be handled automatically by procedures AddObserver() and RemoveObserver().

EnableExplicit is missing 3 times: In each module, and in the demo part of the program.

Re: Subscriber/Observer Pattern

Posted: Thu Sep 04, 2025 11:49 am
by Kiffi
RemoveObsererver -> RemoveObserver :wink:

Re: Subscriber/Observer Pattern

Posted: Thu Sep 04, 2025 4:01 pm
by Little John
:-)

Re: Subscriber/Observer Pattern

Posted: Thu Sep 04, 2025 5:50 pm
by Skipper
Hi Phollyer,

For code like this it would have been nice to have generics...

Thanks for posting!

Cheers,
Skipper

Re: Subscriber/Observer Pattern

Posted: Thu Sep 04, 2025 7:41 pm
by Piero
Can you please stop?
I'm tired of learning from this Forum! :? :x

Re: Subscriber/Observer Pattern

Posted: Fri Sep 05, 2025 12:47 am
by idle
Thanks for sharing
you could also add a mutex to make it thread safe.