1. Introduction
In this post, we are going to explore observer design pattern in Arduino board. Yes. We can use callback function and this will make it easier. But the problem is the callback function has to be static and so far we can’t use std::function (standard c++ library) in Arduino board.
Be warned that what we are going to see later is not full–fledged observer design pattern. We can’t assign multiple observers for this code. We can only assign only one observer for now. We are not going to add multiple observers here to make the observer pattern as simple as possible. However, adding/removing multiple observers can be done using object array and proper tracking of objects.
Download
The whole project can be found from this github.
2. Environment
The project is built using Microsoft Visual Studio with Visualmicro plugin. You can use any available IDE either in Microsoft or Linux environment. The job of IDE here is to help you to write your design logic faster without going through error checking and so on.
3. Class Design
We only have three classes here.
- Observer
- ObserverTester (Concrete class)
- Subject
The above UML diagram [retrieved from wikipedia] will clarify the idea. One thing to take note is that we are talking about the observer pattern here, not publish-subscribe pattern which is using different approach to get an update. The pattern design here is that the observer
will first attach the subject
to itself. When subject wants to notify some updated data due to change in value, the subject will notify the observer. Once the observer get notified, the observer will perform necessary actions based on the received value. The ObserverTester
is derived from the observer so that different derived observers can maintain as the observer pattern.
3.1 Observer class
First we will look at the Observer class. This class is the base class and it only has one function and one virtual function.
Observer.h
class Subject;
class Observer {
public:
void attachSubject(Subject *subject);
virtual void onReceivedDataFromSubject(const Subject*) = 0;
};
Observer.cpp
#include "Observer.h"
#include "Subject.h"
void Observer::attachSubject(Subject * subject) {
subject->registerObserver(this);
}
3.2 Subject
The subject
class can register and unregister a observer and it can hold an observer. It will notify an observer if there is a change in value.
Subject.h
class Observer;
class Subject {
public:
Subject();
void registerObserver(Observer*);
void unregisterObserver();
int getValue() const;
void setVal(const int val);
private:
int mValue;
void _notifyObserver();
Observer* mObserver;
};
Subject.cpp
#include "Subject.h"
#include "Observer.h"
Subject::Subject() {
}
void Subject::registerObserver(Observer* obs) {
mObserver = obs; //we will only allow one observer
}
void Subject::unregisterObserver() {
mObserver = nullptr;
}
int Subject::getValue() const {
return mValue;
}
void Subject::_notifyObserver() {
if (mObserver != nullptr) {
mObserver->onReceivedDataFromSubject(this);
}
}
void Subject::setVal(const int val) {
mValue = val;
_notifyObserver(); //since there is a change in value, notify the observer
}
3.3 ObserverTester
The ObserverTester
is derived from Observer
class and has to override onReceivedDataFromSubject
function. Upon arriving data from the subject, the observerTester print out data which is from Subject
instance.
ObserverTester.h
#include "Observer.h"
class ObserverTester : public Observer
{
void onReceivedDataFromSubject(const Subject*) override;
};
ObserverTester.cpp
#include "ObserverTester.h"
#include "Subject.h"
void ObserverTester::onReceivedDataFromSubject(const Subject *sub) {
Serial.print("Value is "); Serial.println(sub->getValue());
}
3.4 Observer Pattern Test
This is the ino Arduino file to run using observer pattern class. We only need Serial
port to monitor the value. Make sure set the baud rate to 115200
on the serial monitor to see the value correctly.
As mentioned eailer, the ObserverTester
will first attach Subject
. We will change data of subject by setting value using setVal
function. This will cause the subject to notify the observerTester. The observerTester then print out the data of subject on the serial monitor.
Remember that the subject can register and unregister an observer. After the subject unregistered the observerTester from itself using unregisterObserver()
function, the observerTest will no longer receive any update from the subject.
Once the subject registered again using registerObserver(&observerTester)
function, the observerTester will receive the data from the subject again.
ObserverPattenTest.ino
#include "ObserverTester.h"
#include "Observer.h"
#include "Subject.h"
Subject subject;
ObserverTester observerTester;
void setup()
{
Serial.begin(115200);
observerTester.attachSubject(&subject);
}
void loop()
{
for (int i = 0; i < 10; i++) {
subject.setVal(i); //this will print data on Serial Monitor
delay(500);
}
Serial.println("Going to unregister Observer");
subject.unregisterObserver();
for (int i = 0; i < 10; i++) {
subject.setVal(i); // we will not be seeing any value on Serial Monitor because we unregister Observer
delay(500);
}
Serial.println("Going to register Observer again");
subject.registerObserver(&observerTester);
}
Đơn vị chuyển phát nhanh bưu phẩm từ việt nam sang campuchia giá rẻ
ReplyDeleteDỊCH VỤ SHIP NHANH HÀNG HÓA Ở VIỆT NAM
CÔNG TY CHUYỂN PHÁT NHANH BƯU PHẨM Ở VIỆT NAM SANG CAMPUCHIA
Fantastic. Thank you very much for this tutorial.
ReplyDelete