我想知道我对不同事件(例如userLoggedOut
,userRegistered
,userLoggedIn
)的观察者模式的实现是否正确,以下是我的简化代码:
index.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' );
Login.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;
}
}
Email.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";
}
}
我的问题是在处理多个 Action 时,有没有更好的方法来实现观察者模式。
最佳答案
我不认为您的实现是错误的,但这只是不适合我。您的Observable必须知道事件处理程序函数并实现它们(没有某种类型的接口(interface)来保证它们在那里。要继续进行下去,我将确保将附加到Login
的所有内容都应实现一个接口(interface)这样就保证了这些操作功能将在那里,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");
}
然后,您是观察员,将注册如下事件:
class SomeListener {
function __construct() {
$login_instance->register("userLoggedIn", $this, "myLoggedInHandler");
}
function myLoggedInHandler($data = null) {
echo "User Logged In.";
}
}
尽管这只是一种意见,这是一种不同的方法,但是它只需要知道触发什么事件(可以说您的方法也可以这样做,但是Observable应该只调用处理程序方法IMO)。