Commit c48a3f75 authored by Dino Sharich's avatar Dino Sharich ⛹🏿

Refactor observable and observer

Refactor observable and observer to be in line with the new coding standard.
parent 543e74ef
/**
* @file Observable.h
* @author Joshua Lauterbach (joshua@aconno.de)
* @brief triggers observers, generic implementation of observer pattern
* @version 1.0
* @date 2019-10-26
* @file
*
* @copyright aconno GmbH (c) 2019
* @brief Generic implementation of the observer pattern. Observable triggers one or multiple
* observers.
*
* @copyright aconno GmbH (c) 2020
*/
//--------------------------------------------------------------------------------------------------
#ifndef __OBSERVABLE_H__
#define __OBSERVABLE_H__
//-------------------------------- PROTOTYPES ---------------------------------
//--------------------------------------------------------------------------------------------------
namespace Patterns
{
template<class... ObservableParamTypes>
class Observable;
}
//--------------------------------- INCLUDES ----------------------------------
//--------------------------------------------------------------------------------------------------
#include "Error.h"
#include "Observer.h"
#include <forward_list>
//--------------------------------------------------------------------------------------------------
namespace Patterns
{
//-------------------------------- CONSTANTS ----------------------------------
//---------------------------- CLASS DEFINITION -------------------------------
/**
* @brief Inherit this class, to supply an observable hook.
* @brief Provides the generic implementation of Observable pattern. To use the pattern inherit this
* class.
*
* @warning Does not implement inter process commmunication or conntext
* switches. You can use RTOS synchronisation features in combination with this
* to achieve that. Keep in mind, the Observable keeps a dynamic list
* of Observers, so complexity is O(n) and also scales with Observer function
* complexity.
* @note Does not implement inter-process communication or context switches.
*
* @note The Observable keeps a dynamic list of Observers. Complexity of notifying all observers is
* O(n), where n is number of observers. Additional complexity is added by the complexity of
* the notify function.
*
* @tparam ObservableParamTypes type of the parameter the event observer gets
* called with.
* @tparam ObservableParamTypes Types of the parameter observer gets called with.
*/
template<class... ObservableParamTypes>
class Observable {
// structs and enums
public:
// constructors
protected:
/**
* @brief creates the linked list for holding handlers.
* It is heap alloc, to be able to dynamicly add and remove element.
*
*/
constexpr Observable() noexcept : observers() {};
// exposed functions
public:
/**
* @brief registers a new observer that gets called, whenever this
* Observable is triggered. Observer<> objects register themself.
*
* @param observer
*/
void registerObserver(Observer<ObservableParamTypes...>& observer) noexcept;
/**
* @brief unregister given observer.
*
* @param observer
*/
void unregisterObserver(
Observer<ObservableParamTypes...>& observer) noexcept;
// interface implementation
public:
// private variables
private:
// private functions
void unregisterObserver(Observer<ObservableParamTypes...>& observer) noexcept;
private:
/**
* @brief start point of linked list of all observers.
*
*/
/** Start point of the linked list of all the observers. */
std::forward_list<Observer<ObservableParamTypes...>*> observers;
// static functions
private:
// for subclasses
protected:
/**
* @brief trigger this Observable by calling all of its observers.
*
* @param args
*/
void trigger(ObservableParamTypes...);
constexpr Observable() noexcept;
void trigger(ObservableParamTypes... args);
};
} // namespace Patterns
// template classes need this
//--------------------------------------------------------------------------------------------------
#include "../src/Observable.cpp"
#endif //__OBSERVABLE_H__
\ No newline at end of file
//--------------------------------------------------------------------------------------------------
#endif //__OBSERVABLE_H__
//--------------------------------------------------------------------------------------------------
/**
* @file Observer.h
* @author Joshua Lauterbach (joshua@aconno.de)
* @brief abstract class to implementing the observer pattern for Observables.
* @version 1.0
* @date 2019-10-26
* @file
*
* @copyright aconno GmbH (c) 2019
* @brief abstract class to implementing the observer pattern for Observables.
*
* @copyright aconno GmbH (c) 2020
*/
//--------------------------------------------------------------------------------------------------
#ifndef __OBSERVER_H__
#define __OBSERVER_H__
//-------------------------------- PROTOTYPES ---------------------------------
//--------------------------------------------------------------------------------------------------
namespace Patterns
{
......@@ -20,70 +19,57 @@ template<class... ObservableParamTypes>
class Observer;
}
//--------------------------------- INCLUDES ----------------------------------
//--------------------------------------------------------------------------------------------------
#include "Observable.h"
//--------------------------------------------------------------------------------------------------
namespace Patterns
{
//-------------------------------- CONSTANTS ----------------------------------
//---------------------------- CLASS DEFINITION -------------------------------
/**
* @brief handles Observables
* @brief Used to receive the notifications from the observable.
*
* @note One observer can be registered to ONE observable, in contrast to an observable which can
* notify multiple observers.
*
* @warning Does not implement inter process commmunication or conntext
* switches. You can use RTOS synchronisation features in combination with this
* to achieve that. Keep in mind, the Observable keeps a dynamic list
* of Observers, so complexity is O(n) and also scales with Observer function
* complexity.
* @note Does not implement inter-process communication or context switches.
*
* @note The Observable keeps a dynamic list of Observers. Complexity of notifying all observers is
* O(n), where n is number of observers. Additional complexity is added by the complexity of
* the notify function.
*
* @tparam ObservableParamTypes type of emitted arguments.
* @tparam ObservableParamTypes Types of the parameter observer gets called with.
*/
template<class... ObservableParamTypes>
class Observer {
// structs and enums
public:
// constructors
protected:
/**
* @brief Construct a new Observer object and register to Observable
*
* @param sub Observable to subscribe to
*/
Observer(Observable<ObservableParamTypes...>& sub);
/**
* @brief Destroy the Observer object and unsubscribe from Observable
*
*/
~Observer();
// exposed functions
public:
// interface
public:
/**
* @brief implement this to react to Observables.
* @brief Virtual function used to handle the trigger from an observable.
*
* @param observable object beeing observed.
* @param params
* @param[in] observable Class being observed.
* @param[in] params Parameter passed from the observable.
*/
virtual void handle(Observable<ObservableParamTypes...>& observable,
ObservableParamTypes... params) = 0;
virtual void handleObservable(Observable<ObservableParamTypes...>& observable,
ObservableParamTypes... params) = 0;
// private variables
private:
/** Observable that triggers this observer. */
Observable<ObservableParamTypes...>& observable;
// private functions
private:
// static functions
private:
protected:
Observer(Observable<ObservableParamTypes...>& observable);
~Observer();
};
} // namespace Patterns
//--------------------------------------------------------------------------------------------------
#include "../src/Observer.cpp"
#endif //__OBSERVER_H__
\ No newline at end of file
//--------------------------------------------------------------------------------------------------
#endif //__OBSERVER_H__
//--------------------------------------------------------------------------------------------------
\ No newline at end of file
/**
* @file Observable.cpp
* @author Joshua Lauterbach (joshua@aconno.de)
* @brief triggers observers
* @version 1.0
* @date 2019-10-26
* @file
*
* @copyright aconno GmbH (c) 2019
* @brief Generic implementation of the observer pattern. Observable triggers one or multiple
* observers.
*
* @copyright aconno GmbH (c) 2020
*/
//--------------------------------- INCLUDES ----------------------------------
//--------------------------------------------------------------------------------------------------
#include "Observable.h"
//--------------------------- STRUCTS AND ENUMS -------------------------------
//--------------------------------------------------------------------------------------------------
//-------------------------------- CONSTANTS ----------------------------------
/**
* @brief Creates the linked list for holding handlers. List is dynamically allocated.
*/
constexpr Observable() noexcept : observers {} {};
//------------------------------ CONSTRUCTOR ----------------------------------
//--------------------------------------------------------------------------------------------------
//--------------------------- EXPOSED FUNCTIONS -------------------------------
template <class... ObservableParamTypes>
/**
* @brief Registers a new observer. Observer gets called whenever "trigger" is called.
*
* @param[in] observer New class that will be triggered by this observable.
*/
template<class... ObservableParamTypes>
void Patterns::Observable<ObservableParamTypes...>::registerObserver(
Observer<ObservableParamTypes...>& observer) noexcept
{
observers.push_front(&observer);
}
template <class... ObservableParamTypes>
//--------------------------------------------------------------------------------------------------
/**
* @brief Removes the observer from the internal list of the observable.
*
* @note If the given observer was not registered before unregistering it is ignored.
*
* @param[in] observer Class that will not be triggered from this observable.
*/
template<class... ObservableParamTypes>
void Patterns::Observable<ObservableParamTypes...>::unregisterObserver(
Observer<ObservableParamTypes...>& observer) noexcept
{
observers.remove(&observer);
}
template <class... ObservableParamTypes>
void Patterns::Observable<ObservableParamTypes...>::trigger(
ObservableParamTypes... args)
//--------------------------------------------------------------------------------------------------
/**
* @brief Trigger this Observable by calling all of its observers.
*
* @param[in] args Arguments that are used to notify the observer.
*/
template<class... ObservableParamTypes>
void Patterns::Observable<ObservableParamTypes...>::trigger(ObservableParamTypes... args)
{
// call every single observer
for (auto observer : observers) {
observer->handle(*this, std::forward<ObservableParamTypes>(args)...);
observer->handleObservable(*this, std::forward<ObservableParamTypes>(args)...);
}
}
//----------------------- INTERFACE IMPLEMENTATIONS ---------------------------
//--------------------------- PRIVATE FUNCTIONS -------------------------------
//---------------------------- STATIC FUNCTIONS -------------------------------
\ No newline at end of file
//--------------------------------------------------------------------------------------------------
\ No newline at end of file
/**
* @file Observer.cpp
* @author Joshua Lauterbach (joshua@aconno.de)
* @brief implements observer pattern for Observables
* @version 1.0
* @date 2019-12-09
* @file
*
* @copyright aconno GmbH (c) 2019
* @brief abstract class to implementing the observer pattern for Observables.
*
* @copyright aconno GmbH (c) 2020
*/
//--------------------------------- INCLUDES ----------------------------------
//--------------------------------------------------------------------------------------------------
#include "Observer.h"
//--------------------------- STRUCTS AND ENUMS -------------------------------
//-------------------------------- CONSTANTS ----------------------------------
//------------------------------ CONSTRUCTOR ----------------------------------
//--------------------------- EXPOSED FUNCTIONS -------------------------------
//--------------------------------------------------------------------------------------------------
/**
* @brief Construct a observer object and register it to an observable.
*
* @param[in] observable Observable that this observable will watch.
*/
template <class... ObservableParamTypes>
Patterns::Observer<ObservableParamTypes...>::Observer(
Observable<ObservableParamTypes...>& observable)
......@@ -29,14 +25,15 @@ Patterns::Observer<ObservableParamTypes...>::Observer(
observable.registerObserver(*this);
}
//--------------------------------------------------------------------------------------------------
/**
* @brief Unsubscribe from the defined observable and destroy this instance.
*/
template <class... ObservableParamTypes>
Patterns::Observer<ObservableParamTypes...>::~Observer()
{
observable.unregisterObserver(*this);
}
//----------------------- INTERFACE IMPLEMENTATIONS ---------------------------
//--------------------------- PRIVATE FUNCTIONS -------------------------------
//---------------------------- STATIC FUNCTIONS -------------------------------
\ No newline at end of file
//--------------------------------------------------------------------------------------------------
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment