What is the observer pattern?

The observer pattern is a major behavioral design pattern. It allows objects (observers) that have subscribed to an event to wait for input and react to it when notified. This means they don’t have to continuously keep checking whether the input has been provided or not. The main subject maintains a list of all the observers and whenever the event occurs, it notifies the observers so they can update their states accordingly.

Let’s look at a real-life example that we can map to this pattern. Consider a website that posts interesting articles. Every day, you visit the site to check for new articles and if there is none, you revisit after some time/days. What if you get a subscription to the website instead? Once you have the subscription, you’ll get notified every time a new article is posted. So now, instead of checking the site every few hours, you just wait for the notification about a new article.

  • In plain words

  • Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified.

  • Wikipedia says

The observer pattern is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods.

When to use the observer pattern?

  • To improve code management by breaking down large applications into a system of loosely-coupled objects
  • provide greater flexibility by enabling a dynamic relationship between observers and subscribers which is otherwise not possible due to tight coupling
  • improve communication between different parts of the application
  • create a one-to-many dependency between objects that are loosely coupled

Example

class JobPost
{
    protected $title;
 
    public function __construct(string $title)
    {
        $this->title = $title;
    }
 
    public function getTitle()
    {
        return $this->title;
    }
}
 
class JobSeeker implements Observer
{
    protected $name;
 
    public function __construct(string $name)
    {
        $this->name = $name;
    }
 
    public function onJobPosted(JobPost $job)
    {
        // Do something with the job posting
        echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle();
    }
}

Then we have our job postings to which the job seekers will subscribe

class EmploymentAgency implements Observable
{
    protected $observers = [];
 
    protected function notify(JobPost $jobPosting)
    {
        foreach ($this->observers as $observer) {
            $observer->onJobPosted($jobPosting);
        }
    }
 
    public function attach(Observer $observer)
    {
        $this->observers[] = $observer;
    }
 
    public function addJob(JobPost $jobPosting)
    {
        $this->notify($jobPosting);
    }
}

Then it can be used as

// Create subscribers
$johnDoe = new JobSeeker('John Doe');
$janeDoe = new JobSeeker('Jane Doe');
 
// Create publisher and attach subscribers
$jobPostings = new EmploymentAgency();
$jobPostings->attach($johnDoe);
$jobPostings->attach($janeDoe);
 
// Add a new job and see if subscribers get notified
$jobPostings->addJob(new JobPost('Software Engineer'));
 
// Output
// Hi John Doe! New job posted: Software Engineer
// Hi Jane Doe! New job posted: Software Engineer