TungNT (Blue)

tungnt.blue@gmail.com

User Tools

Site Tools


development:software-architecture:design-patterns:observer

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
development:software-architecture:design-patterns:observer [2024/08/13 10:09] tungntdevelopment:software-architecture:design-patterns:observer [2024/08/19 09:51] (current) – [Ví dụ 3:] tungnt
Line 10: Line 10:
  
 {{ :development:software-architecture:design-patterns:observer-comic-1-en-2x.png |}} {{ :development:software-architecture:design-patterns:observer-comic-1-en-2x.png |}}
 +
 +**Sử dụng 2 interface có sẵn của PHP (SplSubject, SplObserver):**
 +  * http://php.net/manual/en/class.splsubject.php
 +  * http://php.net/manual/en/class.splobserver.php
 +  * https://www.php.net/manual/en/class.splobjectstorage.php
  
 ===== Ví dụ 1: ===== ===== Ví dụ 1: =====
 +
 +<file php>
 +<?php
 +
 +/**
 + * Subject,that who makes news
 + */
 +class Newspaper implements \SplSubject{
 +    private $name;
 +    private $observers = array();
 +    private $content;
 +    
 +    public function __construct($name) {
 +        $this->name = $name;
 +    }
 +
 +    //add observer
 +    public function attach(\SplObserver $observer) {
 +        $this->observers[] = $observer;
 +    }
 +    
 +    //remove observer
 +    public function detach(\SplObserver $observer) {
 +        
 +        $key = array_search($observer,$this->observers, true);
 +        if($key){
 +            unset($this->observers[$key]);
 +        }
 +    }
 +    
 +    //set breakouts news
 +    public function breakOutNews($content) {
 +        $this->content = $content;
 +        $this->notify();
 +    }
 +    
 +    public function getContent() {
 +        return $this->content." ({$this->name})";
 +    }
 +    
 +    //notify observers(or some of them)
 +    public function notify() {
 +        foreach ($this->observers as $value) {
 +            $value->update($this);
 +        }
 +    }
 +}
 +
 +/**
 + * Observer,that who recieves news
 + */
 +class Reader implements SplObserver{
 +    private $name;
 +    
 +    public function __construct($name) {
 +        $this->name = $name;
 +    }
 +    
 +    public function update(\SplSubject $subject) {
 +        echo $this->name.' is reading breakout news <b>'.$subject->getContent().'</b><br>';
 +    }
 +}
 +
 +$newspaper = new Newspaper('Newyork Times');
 +
 +$allen = new Reader('Allen');
 +$jim = new Reader('Jim');
 +$linda = new Reader('Linda');
 +
 +//add reader
 +$newspaper->attach($allen);
 +$newspaper->attach($jim);
 +$newspaper->attach($linda);
 +
 +//remove reader
 +$newspaper->detach($linda);
 +
 +//set break outs
 +$newspaper->breakOutNews('USA break down!');
 +
 +//=====output======
 +//Allen is reading breakout news USA break down! (Newyork Times)
 +//Jim is reading breakout news USA break down! (Newyork Times)
 +</file>
 +
 +===== Ví dụ 2: =====
 +
 +<file php>
 +<?php 
 +
 +// Example implementation of Observer design pattern:
 +
 +class MyObserver1 implements SplObserver {
 +    public function update(SplSubject $subject) {
 +        echo __CLASS__ . ' - ' . $subject->getName();
 +    }
 +}
 +
 +class MyObserver2 implements SplObserver {
 +    public function update(SplSubject $subject) {
 +        echo __CLASS__ . ' - ' . $subject->getName();
 +    }
 +}
 +
 +class MySubject implements SplSubject {
 +    private $_observers;
 +    private $_name;
 +
 +    public function __construct($name) {
 +        $this->_observers = new SplObjectStorage();
 +        $this->_name = $name;
 +    }
 +
 +    public function attach(SplObserver $observer) {
 +        $this->_observers->attach($observer);
 +    }
 +
 +    public function detach(SplObserver $observer) {
 +        $this->_observers->detach($observer);
 +    }
 +
 +    public function notify() {
 +        foreach ($this->_observers as $observer) {
 +            $observer->update($this);
 +        }
 +    }
 +
 +    public function getName() {
 +        return $this->_name;
 +    }
 +}
 +
 +$observer1 = new MyObserver1();
 +$observer2 = new MyObserver2();
 +
 +$subject = new MySubject("test");
 +
 +$subject->attach($observer1);
 +$subject->attach($observer2);
 +$subject->notify();
 +
 +/* 
 +will output:
 +
 +MyObserver1 - test
 +MyObserver2 - test
 +*/
 +
 +$subject->detach($observer2);
 +$subject->notify();
 +
 +/* 
 +will output:
 +
 +MyObserver1 - test
 +*/
 +
 +?>
 +</file>
 +
 +===== Ví dụ 3: =====
 +
 +{{ :development:software-architecture:design-patterns:observerstructure-2x.png |}}
 +
 +<file php>
 +<?php
 +
 +namespace RefactoringGuru\Observer\Conceptual;
 +
 +/**
 + * PHP has a couple of built-in interfaces related to the Observer pattern.
 + *
 + * Here's what the Subject interface looks like:
 + *
 + * @link http://php.net/manual/en/class.splsubject.php
 + *
 +     interface SplSubject
 +     {
 +         // Attach an observer to the subject.
 +         public function attach(SplObserver $observer);
 + *
 +         // Detach an observer from the subject.
 +         public function detach(SplObserver $observer);
 + *
 +         // Notify all observers about an event.
 +         public function notify();
 +     }
 + *
 + * There's also a built-in interface for Observers:
 + *
 + * @link http://php.net/manual/en/class.splobserver.php
 + *
 +     interface SplObserver
 +     {
 +         public function update(SplSubject $subject);
 +     }
 + */
 +
 +/**
 + * The Subject owns some important state and notifies observers when the state
 + * changes.
 + */
 +class Subject implements \SplSubject
 +{
 +    /**
 +     * @var int For the sake of simplicity, the Subject's state, essential to
 +     * all subscribers, is stored in this variable.
 +     */
 +    public $state;
 +
 +    /**
 +     * @var \SplObjectStorage List of subscribers. In real life, the list of
 +     * subscribers can be stored more comprehensively (categorized by event
 +     * type, etc.).
 +     */
 +    private $observers;
 +
 +    public function __construct()
 +    {
 +        $this->observers = new \SplObjectStorage();
 +    }
 +
 +    /**
 +     * The subscription management methods.
 +     */
 +    public function attach(\SplObserver $observer): void
 +    {
 +        echo "Subject: Attached an observer.\n";
 +        $this->observers->attach($observer);
 +    }
 +
 +    public function detach(\SplObserver $observer): void
 +    {
 +        $this->observers->detach($observer);
 +        echo "Subject: Detached an observer.\n";
 +    }
 +
 +    /**
 +     * Trigger an update in each subscriber.
 +     */
 +    public function notify(): void
 +    {
 +        echo "Subject: Notifying observers...\n";
 +        foreach ($this->observers as $observer) {
 +            $observer->update($this);
 +        }
 +    }
 +
 +    /**
 +     * Usually, the subscription logic is only a fraction of what a Subject can
 +     * really do. Subjects commonly hold some important business logic, that
 +     * triggers a notification method whenever something important is about to
 +     * happen (or after it).
 +     */
 +    public function someBusinessLogic(): void
 +    {
 +        echo "\nSubject: I'm doing something important.\n";
 +        $this->state = rand(0, 10);
 +
 +        echo "Subject: My state has just changed to: {$this->state}\n";
 +        $this->notify();
 +    }
 +}
 +
 +/**
 + * Concrete Observers react to the updates issued by the Subject they had been
 + * attached to.
 + */
 +class ConcreteObserverA implements \SplObserver
 +{
 +    public function update(\SplSubject $subject): void
 +    {
 +        if ($subject->state < 3) {
 +            echo "ConcreteObserverA: Reacted to the event.\n";
 +        }
 +    }
 +}
 +
 +class ConcreteObserverB implements \SplObserver
 +{
 +    public function update(\SplSubject $subject): void
 +    {
 +        if ($subject->state == 0 || $subject->state >= 2) {
 +            echo "ConcreteObserverB: Reacted to the event.\n";
 +        }
 +    }
 +}
 +
 +/**
 + * The client code.
 + */
 +
 +$subject = new Subject();
 +
 +$o1 = new ConcreteObserverA();
 +$subject->attach($o1);
 +
 +$o2 = new ConcreteObserverB();
 +$subject->attach($o2);
 +
 +$subject->someBusinessLogic();
 +$subject->someBusinessLogic();
 +
 +$subject->detach($o2);
 +
 +$subject->someBusinessLogic();
 +</file>
 +
 +===== Ví dụ 4: =====
  
 <file php> <file php>
Line 224: Line 538:
 </file> </file>
  
-====== Tham khảo ======+===== Tham khảo =====
  
   * https://refactoring.guru/design-patterns/observer   * https://refactoring.guru/design-patterns/observer
   * https://moezmissaoui.medium.com/the-observer-design-pattern-in-laravel-a-comprehensive-guide-cdac37601e7a   * https://moezmissaoui.medium.com/the-observer-design-pattern-in-laravel-a-comprehensive-guide-cdac37601e7a
   * https://medium.com/@mansha99/better-laravel-monoliths-observer-pattern-ff9119db5b65   * https://medium.com/@mansha99/better-laravel-monoliths-observer-pattern-ff9119db5b65
 +  * https://www.youtube.com/watch?v=7J5pRc2vzWk
  
development/software-architecture/design-patterns/observer.1723543783.txt.gz · Last modified: 2024/08/13 10:09 by tungnt

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki