PHP 中的观察者模式 - 不同事件的正确实践

Pet*_*one 5 php oop design-patterns observer-pattern

我想知道我对不同事件(例如“ userLoggedOut”、“ userRegistered”、“ userLoggedIn”)的观察者模式的实现是否正确,以下是我的简化代码:

索引.php

$login = new \Observer\Observable\Login;
$userData = $login->getData();

$login->attach( new \Observer\Observer\Email );

$login->notify( 'userLoggedIn' );
$login->notify( 'userLoggedOut', $userData );
$login->notify( 'userRegistered' );
Run Code Online (Sandbox Code Playgroud)

登录.php

namespace Observer\Observable;
use Observer\Interfaces;

class Login implements Interfaces\Observable {

    private $observers = array();

    function attach( Interfaces\Observer $object ) {

        $this->observers[] = $object;

    }

    function getObservers() {

        return $this->observers;

    }

    function notify( $action, $data = null ) {

        foreach( $this->observers as $observer ) :

            if( method_exists( $observer, $action ) ) $observer->$action( $data );

        endforeach;

    }

}
Run Code Online (Sandbox Code Playgroud)

电子邮件.php

namespace Observer\Observer;
use Observer\Interfaces;

class Email implements Interfaces\Observer {

    function userLoggedIn( $data = null ) {

        echo "email user logged in";

    }

    function userLoggedOut( $data = null ) {

        echo "email user logged out";

    }

    function userRegistered( $data = null ) {

        echo "email user registered";

    }

}
Run Code Online (Sandbox Code Playgroud)

我的问题是在处理多个动作时是否有更好的方法来实现观察者模式。

Bra*_*uck 3

我不认为你的实施是错误的,但它只是不适合我。你的 Observable 必须知道事件处理函数并实现它们(没有某种接口来保证它们在那里。为了继续你要走的路,我会确保任何附加的东西都应该实现一个Login接口,保证这些操作函数将在那里。从那里,Login 不必了解有关观察者的任何信息,它只需调用函数即可。

我采取的另一种方法是指定事件名称的处理程序,如下所示:

class Observable {
    protected static $event_names = array();
    protected $observers = array();

    function __construct() {
        foreach (static::$event_names as $event_name) {
            $this->observers[$event_name] = array();
        }
    }

    function register($event, $object, $handler) {
        if (array_key_exists($event, $this->observers)) {
            $this->observers[$event][] = array($object, $handler);
        } else {
            echo "Invalid event \"$event\"!";
        }
    }

    function trigger($event, $data = null) {
        foreach ($this->observers[$event] as $observer) {
            $observer[0]->$observer[1]($data);
        }
    }
}

class Login extends Observable {
    protected static $event_names = array("userLoggedIn", "userLoggedOut", "userRegistered");
}
Run Code Online (Sandbox Code Playgroud)

然后你作为观察者会注册这样的事件:

class SomeListener {
    function __construct() {
        $login_instance->register("userLoggedIn", $this, "myLoggedInHandler");
    }

    function myLoggedInHandler($data = null) {
        echo "User Logged In.";
    }
}
Run Code Online (Sandbox Code Playgroud)

这只是一种意见,它是一种不同的方法,但它只需要知道什么事件会触发(你的方法也可以这样做,但在我看来,Observable 应该简单地调用处理程序方法)。

  • 嘿@izuriel,我知道......我想很难知道这些事情,因为我想每个人都有自己的细微差别和实现。当你刚接触设计模式之类的东西时,这总是很困难,因为有很多人说不同的事情。我只是在一点一点地努力进步,并从像你这样的人那里获取知识。 (2认同)