>  기사  >  백엔드 개발  >  PHP의 관찰자 패턴에 대한 심층 분석

PHP의 관찰자 패턴에 대한 심층 분석

青灯夜游
青灯夜游앞으로
2021-06-30 19:43:243284검색

이전 기사 "한 기사로 PHP의 어댑터 모드 이해하기"에서 PHP의 어댑터 모드를 소개했습니다. 이 기사에서는 PHP의 관찰자 모드를 이해하는 데 도움이 됩니다.

PHP의 관찰자 패턴에 대한 심층 분석

관찰자님, 이 캐릭터는 많은 SF 작품에 등장하는 것 같습니다. 예를 들어, 내가 가장 좋아하는 미국 TV 시리즈 중 하나인 '프린지(Fringe)'는 이 시리즈에서 관찰자들이 시공간을 끊임없이 여행하며 다양한 사람이나 사물을 기록하는 모습을 담고 있다. 그러나 디자인 패턴에서의 관찰자는 단지 옆으로 서서 지켜보는 것이 아니다. 여기서 관찰자는 주체에 일어나는 상태 변화에 따라 상응하는 행동을 취한다.

Gof 클래스 다이어그램 및 설명

GoF 정의: 객체 간의 일대다 종속 관계를 정의합니다. 객체의 상태가 변경되면 이에 의존하는 모든 객체에 알림이 전송되고 자동으로 업데이트됩니다.

GoF 클래스 다이어그램:

PHP의 관찰자 패턴에 대한 심층 분석

코드 구현

interface Observer
{
    public function update(Subject $subject): void;
}

관찰자의 추상 인터페이스는 말할 것도 없고 단지 특정 업데이트를 구현하도록 허용합니다.

class ConcreteObserver implements Observer
{
    private $observerState = '';
    function update(Subject $subject): void
    {
        $this->observerState = $subject->getState();
        echo '执行观察者操作!当前状态:' . $this->observerState;
    }
}

특정 관찰자가 업데이트( ) 메소드. 여기서는 상태를 얻을 수 있도록 Subject 클래스를 얻습니다.

class Subject
{
    private $observers = [];
    private $stateNow = '';
    public function attach(Observer $observer): void
    {
        array_push($this->observers, $observer);
    }
    public function detach(Observer $observer): void
    {
        $position = 0;
        foreach ($this->observers as $ob) {
            if ($ob == $observer) {
                array_splice($this->observers, ($position), 1);
            }
            ++$position;
        }
    }
    public function notify(): void
    {
        foreach ($this->observers as $ob) {
            $ob->update($this);
        }
    }
}

Subject 상위 클래스는 관찰자 배열을 유지하고 이 배열을 통해 추가, 삭제 및 반복하는 메소드를 갖습니다. 모든 관찰자를 관리합니다

class ConcreteSubject extends Subject{
    public function setState($state)
    {
        $this->stateNow = $state;
        $this->notify();
    }

    public function getState()
    {
        return $this->stateNow;
    }
}

Subject의 구현 클래스는 상태만 업데이트합니다. 이 상태가 변경되면 관찰자 순회 메서드가 호출되어 모든 관찰자의 update() 작업을 수행합니다.

  • Observer는 실제로 업데이트( update) 자체적으로, Subject는 관찰자를 일괄적으로 실행할 수 있습니다. 대상 클래스의 코드를 수정할 필요가 없으며 외부에서 추가하기만 하면 됩니다. 따라서 대상이 관찰자로부터 분리되도록 하십시오. 서로의 상황은 신경쓰지 않아도 됩니다
  • 관찰자는 대상의 상태를 기록할 수도 있고 기록할 필요도 없습니다. 예를 들어 문자 메시지를 보낸 후 데이터베이스를 업데이트하거나 작업을 삽입하면 우리는 이를 수행합니다. 문자 메시지 인터페이스가 성공적으로 전송된 후에만 수행됩니다. SMS 데이터의 상태를 수정하기만 하면 됩니다. 반드시 관찰자에게 대상 전송 상태를 전송할 필요는 없습니다.
  • 클래스가 변경되면 얼마나 많은 다른 클래스가 있는지 알 수 없습니다. 이때 관찰자는 매우 유용합니다
  • 관찰자 패턴에는 여전히 결합이 있습니다. 즉, 관찰자가 update()를 구현하지 않으면 대상 클래스에 관찰자 개체 목록이 있습니다. 방법을 사용하면 문제가 발생합니다

저희 휴대폰 공장 얘기를 해보자면 이번에는 좋은데, 저는 모방폰(관찰자)들의 표적이 되었습니다. 제가 어떤 기능(상태 업데이트)을 제공하면 그들은 동일한 기능(업데이트)을 수행하며 내 내용을 기반으로 업데이트도 수행합니다. 완곡하게 말하면 마이크로 혁신입니다. 짜증나거나 그렇지 않다고 하더군요. 글쎄요, 저는 또한 시장 조사원(관찰자) 그룹을 보내서 다른 사람들의 휴대폰에 어떤 기능(상태 업데이트)이 있는지 관찰하는 데 도움을 주었습니다. 그런 다음 우리는 이를 복사하여 미세한 혁신을 만들어 모두가 함께 발전할 수 있도록 하겠습니다. . !

전체 코드: https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/observer.php

Example

이번에는 주문부터 시작하겠습니다. 하지만 여전히 문자 메시지를 보내는 문제가 있습니다. 일반 전자상거래 플랫폼에서 누군가 주문을 하면 재고를 수정하거나, 누군가가 주문했다는 사실을 판매자에게 문자 메시지나 푸시 알림으로 알리고, 구매자에게 이를 알리는 등 해야 할 일이 많습니다. 주문이 성공적으로 이루어졌고 결제가 성공적으로 이루어졌습니다. 즉, 한 가지 일이 발생하면 다양한 사건이 발생하게 됩니다. 사실 이는 또 다른 매우 유명한 모델인 구독 및 게시 모델로 이어집니다. 이 모드는 옵저버의 업그레이드 모드라고 할 수 있습니다. 이 시리즈에서는 자세히 다루지는 않지만 Laravel의 게시 및 구독이벤트 모니터링 측면을 살펴볼 수 있습니다.

주문 판매 클래스 다이어그램

PHP의 관찰자 패턴에 대한 심층 분석

전체 소스 코드: https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/order-observer.php

interface Observer
{
    public function update($obj);
}

class Message implements Observer
{
    //....

    function update($obj)
    {
        echo '发送新订单短信(' . $obj->mobile . ')通知给商家!';
    }

    //....
}

class Goods implements Observer
{
    //....

    public function update($obj)
    {
        echo '修改商品' . $obj->goodsId . '的库存!';
    }

    //....
}

class Order
{
    private $observers = [];
    public function attach($ob)
    {
        $this->observers[] = $ob;
    }

    public function detach($ob)
    {
        $position = 0;
        foreach ($this->observers as $ob) {
            if ($ob == $observer) {
                array_splice($this->observers, ($position), 1);
            }
            ++$position;
        }
    }
    public function notify($obj)
    {
        foreach ($this->observers as $ob) {
            $ob->update($obj);
        }
    }
    public function sale()
    {
        // 商品卖掉了
        // ....
        $obj = new stdClass();
        $obj->mobile = '13888888888';
        $obj->goodsId = 'Order11111111';
        $this->notify($obj);
    }
}

$message = new Message();
$goods = new Goods();
$order = new Order();
$order->attach($message);
$order->attach($goods);

// 订单卖出了!!
$order->sale();

지침

  • GoF 클래스 다이어그램을 완전히 준수하지는 않습니다. GoF는 성경이지만 완전히 준수할 필요는 없습니다. 특정 비즈니스 상황에 맞게 적절하게 조정할 수 있습니다.
  • 주문 상태는 판매를 통해 변경됩니다. 메소드 마지막으로 알림 메소드를 직접 호출하여 관찰자를 호출합니다
  • 문자 메시지 전송과 푸시 메시지 전송은 별도의 관찰자에 의해 구현될 수 있습니다. 이러한 관찰자는 반드시 이 메소드만 가질 필요는 없지만 공통 인터페이스를 구현하는 한,
  • 제품 인벤토리와 메시지 전송은 실제로 전혀 관련이 없는 두 클래스이지만 동일한 인터페이스만 구현하면 됩니다.
  • PHP의 SPL 확장은 우리를 위해 일련의 관찰자 인터페이스를 준비했습니다. 기본적으로 지원되는 관찰자 모드를 사용하면 많은 문제를 줄일 수 있습니다!

SPL 확장은 관찰자 패턴을 구현합니다 - 전체 소스 코드: https://github.com/zhangyue0503/designpatterns-php/blob/master/06.observer/source/spl_observer.php

이 기사는 다음에서 복제되었습니다. : https://juejin.cn/post/6844903930262978574

저자 : 하드코어 프로젝트 매니저

추천 학습 : "PHP Video Tutorial"

위 내용은 PHP의 관찰자 패턴에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제