Observer and Observable¶
To write output messages when desired by the user, the observer pattern is implemented in Ikarus.
Four things are necessary to understand the implementation of observer patterns: Messages, IObservable,
IObserver and Subscriptions.
Messages¶
A message class is a list of possible events that can happen and might be of interest. The messages that are used for nonlinear solvers are listed below as an example.
enum class NonLinearSolverMessages {
BEGIN,
INIT,
ITERATION_STARTED,
ITERATION_ENDED,
RESIDUALNORM_UPDATED,
CORRECTIONNORM_UPDATED,
SOLUTION_CHANGED,
FINISHED_SUCESSFULLY,
END
};
IObservable¶
A class can be observable. The class then sends notifications when events are happening. To become observable, a class
must inherit from IObservable<MessageType>, for example,
this->notify(MessageType::Message) is called at the appropriate position in the code to send a
notification. This could be, for example,
IObserver¶
A class can be an observer. The class is then notified when events are happening and can perform actions. A very simple
example is shown below. To become an observer, the class must inherit from IObserver<MessageType>, where MessageType
is the enum of messages to use (see above).
class OurFirstObserver : public IObserver<NonLinearSolverMessages> {
public:
void updateImpl(NonLinearSolverMessages message) override {
if (message == NonLinearSolverMessages::ITERATION_STARTED) std::cout << "Iteration started.\n";
}
};
void updateImpl(MessageType message). In this function, all actions can
be implemented that should be performed when the corresponding message is received.
To connect observer and observable, one has to call observalbe.subscribe(MessageType::Message,observer). Example:
Ikarus::NewtonRaphson nr(...);
auto ourSimpleObserver = std::make_shared<OurFirstObserver>();
nr.subscribe(NonLinearSolverMessages::ITERATION_STARTED, ourSimpleObserver);
};
Subscriptions¶
There are a couple of options for the subscription:
subscribe(MessageType::Message,observer) // (1)!
subscribeAll(observer) // (2)!
subscribeAll({observer1,observer2}) // (3)!
unSubscribe(...) // (4)!
- Subscribes to one specific message.
- Subscribes to all the messages in
enum. - Multiple observers can subscribe at once.
- Unsubscribe from specific messages or all messages.
To send a message together with data, the sender (observable) calls
and the receiver (observer) has to implement To see all available options fordata, we refer to the file observer.hh.