Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explained example for Observer pattern! #150

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 60 additions & 45 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -1794,7 +1794,7 @@ $editor->getContent(); // This is the first sentence. This is second.
😎 Observer
--------
Real world example
> A good example would be the job seekers where they subscribe to some job posting site and they are notified whenever there is a matching job opportunity.
> Let’s assume we have a NewsAgency (the subject) that publishes news. Multiple NewsChannels (the observers) are subscribed to this agency, and whenever there is new news, the agency notifies all its channels.

In plain words
> Defines a dependency between objects so that whenever an object changes its state, all its dependents are notified.
Expand All @@ -1804,80 +1804,95 @@ Wikipedia says

**Programmatic example**

Translating our example from above. First of all we have job seekers that need to be notified for a job posting
Translating our example from above. First of all we have news channels that need to be notified for a news

- Subject Interface: The subject (NewsAgency) will allow observers (NewsChannels) to subscribe, unsubscribe, and notify them when there’s an update.
- Observer Interface: The observers (NewsChannels) will have a method to get updates from the subject.
```php
interface Subject
{
public function subscripeChannel(Observer $observer): void;
public function removeChannel(Observer $observer): void;
public function notify(): void;
}

interface Observer
{
public function update(string $news): void;
}
```
Concrete Subject: Implements the subject interface and maintains a list of observers.
```php
class JobPost
class NewsAgency implements Subject
{
protected $title;
private array $observers = [];
private string $news;

public function __construct(string $title)
public function subscripeChannel(Observer $observer): void
{
$this->title = $title;
$this->observers[] = $observer;
}

public function getTitle()
public function removeChannel(Observer $observer): void
{
return $this->title;
$this->observers = array_filter($this->observers, function ($obs) use ($observer) {
return $obs !== $observer;
});
}
}

class JobSeeker implements Observer
{
protected $name;

public function __construct(string $name)
public function notify(): void
{
$this->name = $name;
foreach ($this->observers as $obs) {
$obs->update($this->news);
}
}

public function onJobPosted(JobPost $job)
public function setNews(string $news): void
{
// Do something with the job posting
echo 'Hi ' . $this->name . '! New job posted: '. $job->getTitle();
$this->news = $news;
$this->notify();
}
}
```
Then we have our job postings to which the job seekers will subscribe
Concrete Observer: Implements the observer interface and reacts to updates from the subject.
```php
class EmploymentAgency implements Observable
class Channel implements Observer
{
protected $observers = [];

protected function notify(JobPost $jobPosting)
{
foreach ($this->observers as $observer) {
$observer->onJobPosted($jobPosting);
}
}
private string $agencyName;

public function attach(Observer $observer)
public function __construct(string $agencyName)
{
$this->observers[] = $observer;
$this->agencyName = $agencyName;
}

public function addJob(JobPost $jobPosting)
public function update(string $news): void
{
$this->notify($jobPosting);
echo "hi {$this->agencyName}, you have a news: {$news} <br />";
}
}
```
Then it can be used as

```php
// Create subscribers
$johnDoe = new JobSeeker('John Doe');
$janeDoe = new JobSeeker('Jane Doe');
// create the channels,
$cbc = new Channel("cbc");
$mbc = new Channel("mbc");

// subscripe them into my subject
$newsAgency = new NewsAgency();
$newsAgency->subscripeChannel($cbc);
$newsAgency->subscripeChannel($mbc);

// set news
$newsAgency->setNews("this new!!");

// Create publisher and attach subscribers
$jobPostings = new EmploymentAgency();
$jobPostings->attach($johnDoe);
$jobPostings->attach($janeDoe);
$newsAgency->removeChannel($cbc);

// Add a new job and see if subscribers get notified
$jobPostings->addJob(new JobPost('Software Engineer'));
$newsAgency->setNews("this the second new!!");

// Output
// Hi John Doe! New job posted: Software Engineer
// Hi Jane Doe! New job posted: Software Engineer
// expected results:
// hi cbc, you have a news: this new!!
// hi mbc, you have a news: this new!!
// hi mbc, you have a news: this the second new!!
```

🏃 Visitor
Expand Down