PDA

View Full Version : Replace the typical observer pattern to the Qt's signal and slot



sajis997
23rd June 2011, 00:29
Hello forum,


I am going through a source code where they have implemented the typical observer pattern and i need to re-implement it using the Qt's signal & slot mechanism.


Any guideline would be very helpful


Regards
Sajjad

Santosh Reddy
23rd June 2011, 01:30
Event source (object class creating the event should be sub-class on QObject) will emit a Qt signal, and observer (also a sub-class of QObject) will connect its slot to the emitted signal

stampede
23rd June 2011, 09:13
In addition, it could be quite useful to declare pure virtual slot void Observer::update( Source * changedSource ) = 0; in Observer class, this way all observers will share the same interface for receiving updates.

observer (also a sub-class of QObject) will connect its slot to the emitted signal
Maybe its a little detail, but I'd leave management of Observers to Watched class. In typical observer pattern ("Gang of Four"), Watched object defines methods for adding and removing Observers, so creating connection could be a part of Watched::add(Observer * o) method (and Watched::remove(Observer* o) could simply call this->disconnect(o)).

sajis997
23rd June 2011, 09:17
Hello Santosh!


thanks for the hint. I am taking an example and let's see it helps me to understand what you tried to explain:




class propertylistwidget : public networkobserver
{
public:

// Implementation of the ProcessorNetworkObserver interface
void networkChanged();
void processorAdded(const Processor* processor);
void processorRemoved(const Processor* processor);
void processorRenamed(const Processor* p, const std::string& prevName);
void connectionsChanged();
void propertyLinkAdded(const PropertyLink* link);
void propertyLinkRemoved(const PropertyLink* link);
void portConnectionAdded(const Port* outport, const Port* inport);
void portConnectionRemoved(const Port* outport, const Port* inport);

};




I am planning to change those functions to signals instead and create some slots which will be containing the definition of those respective functions.

But some times i am sure about the slot functons i have to create . How do i decide that they belong to the corresponding class above or not?



Regards
Sajjad

wysota
23rd June 2011, 09:29
In addition, it could be quite useful to declare pure virtual slot void Observer::update( Source * changedSource ) = 0; in Observer class, this way all observers will share the same interface for receiving updates.
You can use QObject::sender() instead.


Maybe its a little detail, but I'd leave management of Observers to Watched class. In typical observer pattern ("Gang of Four"), Watched object defines methods for adding and removing Observers, so creating connection could be a part of Watched::add(Observer * o) method (and Watched::remove(Observer* o) could simply call this->disconnect(o)).
If you wrap signals and slots in Observer API then what's the point of using signals and slots in the first place?

stampede
23rd June 2011, 10:26
If you wrap signals and slots in Observer API then what's the point of using signals and slots in the first place?
Because maybe later someone will have to replace signals and slots with other notification mechanism. I know, it's only an exercise, anyway I think its good practice to hide implementation details whenever its possible (this applies to your remark with sender() as well, I know here it will work and OP's quesion was about QObject).

wysota
23rd June 2011, 11:22
Because maybe later someone will have to replace signals and slots with other notification mechanism.
But then why use signals and slots at all? You are implementing a complete observer pattern api only to internally use some other mechanism that already implements the same behaviour. The whole point of using signals and slots is that it is a loosely coupled mechanism. If you wrap it in API that requires some dedicated interfaces then you lose this flexibility and you can use those interfaces directly.

stampede
23rd June 2011, 11:56
Benefit of using signals&slots underneath Observer api could be to send update() notifications to observers in thread-safe manner easily.
Anyway I think our discussion doesn't help the OP at all :rolleyes:

wysota
23rd June 2011, 13:23
I think all the OP wanted was to get rid of additional classes implementing the Observer pattern and use signals and slots directly. All those methods listed in the original post are good candidates for signals.

stampede
24th June 2011, 10:01
My bad, looks like I've misunderstood the original post. Forget what I've written here, you were right from the beginning.

Santosh Reddy
24th June 2011, 10:31
Have a look at this (http://www.voreen.org/doc/2.5/propertylistwidget_8h_source.html), I guess you referred to the same example, this library already uses signal & slots.

sajis997
25th June 2011, 01:11
Hello Reddy,

Yes , you are right . They already have it. My question is if i would like to replace their existing observer pattern with signal and slot, what are the procedure do i have to follow?


Regards
Sajjad

Santosh Reddy
25th June 2011, 04:24
Ok, here are some points to start with.

- The lib you referred uses C++'s polymorphism to make calls to concrete observer class objects from a abstract observer class. You can make use of QtC++'s signals to make these calls.
- You can replace the virtual functions (be wise, to replace only the virtual functions which are used to realize observer pattern) in the abstract observer class with signals (these signals will still be new observer manager class).
- All the contrete observer classes which were derived from abstract observer class may no longer need do be so, i.e. they all can be indipendent classes (it's up to your design to have them in class hirarchy, to realize your functunality)
- In the abstract observer class's abstract implementation replace calls to virtual functions with emitting correspoding signals, as said earlier.
- In the new classes (which used to be contrete observer classes), implement corresponding slots, and and connect them to the observer manager class's signals (as and when requied to observe)
- Replace the abstract observer, with a contrete observer manager which manages the observer connections, observable contexts, topics, subjects etc
- Also, as expected all the new classes should be aware of the observable class, which is genreally used to register (connect a slot) an observation instance with concrete observer manager.
- When observing to no longer is needed then disconnet the slot (un-registering the observable)

Note that some of the terms used above may be generic in manner, just to give you a heading.

sajis997
22nd July 2011, 09:54
Hello Santosh,

Thanks for the explanation. Now i have the following snippet that needs to be changed to Qt's signal and slot:



workspace_->getProcessorNetwork()->addObserver(this);




connect(processorNetwork, SIGNAL(networkChanged()),this, SLOT());


In the immediate above code snippet i have changed the virtual functions in the abstract observer class to corresponding and now i am confused to get the SLOT for them. Is there any hint to find the SLOT() for each of the signals. Or i have declare and define them by myself?


Regards
Sajjad

Santosh Reddy
22nd July 2011, 11:03
- In the new classes (which used to be contrete observer classes), implement corresponding slots, and and connect them to the observer manager class's signals (as and when requied to observe)
This should answer it...