# My favourite design pattern: The Observer


## Why Observer is so cool?

Managing complexity in large code base is all about decoupling.  Observer is a perfect tool to do that.  The `Observed` object has no idea about its observers, no dependency injection is required at all, as a result a loose coupling is achieved between two classes of objects where the only common part is the interface they agree upon.

## First iteration

It's a classic design pattern and I'm sure majority (if not all) of engineers know the details behind it, most of us implement it in a slightly different way, depending on the requirements and the code base we are working with though.  Here's my flavour of this design pattern.


```C++
class Observer {
public:
    virtual ~Observer() = default;

    virtual void update() = 0;
};

class Observed {
public:
    virtual ~Observed() = default;

    void addObserver(std::shared_ptr<Observer> observer) final {
        observers.push_back(observer);
    }

    void removeObserver(std::shared_ptr<Observer> observer) final {
        observers.erase(std::remove_if(observers.begin(), observers.end(),
            [observer](const auto o){ return o.lock() == observer; }),
            observers.end());
    }

    void notifyObservers() final {
        for (const auto o : observers) {
            if (auto strong = o.lock()) {
                strong->update();
            }
        }
    }

private:
    std::vector<std::weak_ptr<Observer>> observers;
};
```

This implementation would be used in a following way:

```C++
class ConcreteObserved : public Observed {
public:
};

class ConcreteObserver : public Observer {
public:
    void update() override {
        std::cout << "Received an update" << std::endl;
    }
};

...
ConcreteObserved observed;
auto concreteObserver = std::make_shared<ConcreteObserver>();

observed.addObserver(concreteObserver);
observed.notify();
```

That's how the fundamentals usually look.  The `Observed` object generates `update()` events to notify its observers that something has happened.  There's a couple of problems with this code though, preventing it from being a generic, library implementation that could be used independently.  Let's address these.

### Generic Observer type

First of all, the implementation dictates the API for `Observers`.  Each `Observer` can only be updated using a single `update` function which doesn't take any arguments.  It's impossible to pass any extra data along with the notification.  One could argue that you could change the signature to i.e.:

```c++
void update(std::string details);
```

But that is not really a good solution.  What if I want a different type
than `std::string`?

Often, you'll want to receive updates of more than one type.
Additionally, you'll most likely want to get some information passed in
`update()` as an argument to understand what has changed within the
`Observed` object.  To conclude, the `Observer` can't be defined upfront - it has to be a template parameter.



```C++
template <typename ObserverT>
class Observed {
    ...
    void notifyObservers() {
        // how to implement this?
    }
}
```

Since the `Observer`'s API is unknown up front it's impossible to
implement the notification functions in a generic way.  This could be
solved in a simple manner by delegating the problem to the clients:


```C++
class ClientObserver {
public:
    virtual void updateA(int a) = 0;

    virtual void updateB(std::string b) = 0;
};

class ClientConcreteObserver : public ClientObserver {
public:
    void updateA(int a) {
        std::cout << "got update A with value: " << a << std::endl;
    }

    void updateB(std::string b) {
        std::cout << "got update B with value: " << b << std::endl;
    }
};

class ClientObserved : public Observed<ClientObserver> {
    ...
    void notifyA(int i) {
        for (const auto o : observers) {
            if (auto strong = o.lock()) {
                strong->updateA(i);
            }
        }
    }

    void notifyB(std::string s) {
        for (const auto o : observers) {
            if (auto strong = o.lock()) {
                strong->updateB(s);
            }
        }
    }
};
```
In the code above, the client defines, the `Observer` interface (which
it then implements as well).  Having an abstract observer interface,
allows for creation of `Observed` instances with that particular
type.

Sure, this will work but it leads to a terrible amount of code
duplication.  Each `notify` function is roughly duplicating the same
pattern but with a slightly different update call.  This problem can be
solved in two ways.

#### Pointer to members

Firstly, I'm gonna generalise the implementation of the `notify` function.  It'll now be a function template and it'll look like so:

```C++
    template <typename ReturnT, typename ... ArgsT>
    void notify(ReturnT (ObserverT::*member)(ArgsT...), ArgsT&& ... args) {
        for (const auto o : observers) {
            if (auto strong = o.lock()) {
                (strong.get()->*member)(std::forward<ArgsT>(args)...);
            }
        }
    }
```

Granted, it looks a bit scary but after a minute it becomes clear.  I'm using a pointer to member here and a variadic template to handle function arguments which are perfectly forwarded.  How to use it?

```C++
class ClientObserved : public Observed<Observer> {
public:
};

class ClientConcreteObserver : public Observer {
public:
    void updateA(int a) {
        std::cout << "got update A with value: " << a << std::endl;
    }

    void updateB(std::string b) {
        std::cout << "got update B with value: " << b << std::endl;
    }
};

...
auto co = std::make_shared<ClientConcreteObserver>();
ClientObserved o;

o.addObserver(co);
o.notify(&Observer::updateA, 456);
o.notify(&Observer::updateB, std::string("hello"));
```

That looks good.  The provided implementation is generic enough to exist independently and be reusable.  Just for reference, I'm gonna show another way to implement notifications, using functors.


### Functors

The implementation of `notify` member function becomes simpler and more concise:

```C++
    template <typename FunctorT>
    void notify(FunctorT functor) {
        for (const auto o : observers) {
            if (auto strong = o.lock()) {
                functor(strong.get());
            }
        }
    }
```

In here I expect to receive a functor taking a pointer to `Observer*` type explicitly.  In other words, the function signature becomes as following:

```C++
    void functor(Observer* o, ...);
```

The complexity is shifted to the client side.  In order to use the `notify` function in its current form, functors have to be created in place:


```C++
    using namespace std::placeholders;
    ...

    auto co = std::make_shared<ClientConcreteObserver>();
    ClientObserved o;

    o.addObserver(co);
    o.notify(std::bind(&Observer::updateA, _1, 456));
    o.notify(std::bind(&Observer::updateB, _1, std::string("hello")));
```

All details and a more concise reference can be found on [gitlab](https://gitlab.com/twdev_projects/observer).

