美文网首页
PHP自带的观察者模式接口

PHP自带的观察者模式接口

作者: imjcw | 来源:发表于2018-12-13 10:30 被阅读0次

前言

换了一份新工作,新的环境,新的人,新的系统,新的代码(emmm)。

这两天没事,装装环境,看看代码。

在看到项目文件的时候,有了新的发现。

观察者模式

项目的优惠券类里使用了 观察者设计模式。原本这个也不算新奇,但是让我眼前一亮的是,优惠券类实现了 SplSubject 接口。

SplSubject 这个是什么接口?一看就知道是 PHP 提供的接口,但是作用却不清楚。

第一时间打开官网,找到这个接口的相关文档。

The SplSubject interface is used alongside SplObserver to implement the Observer Design Pattern.

SplSubject 接口是与 SplObserver 一起配合使用实现观察者设计模式的。

SplSubject {
    abstract public void attach ( SplObserver $observer )
    abstract public void detach ( SplObserver $observer )
    abstract public void notify ( void )
}

从官网提供的信息可以看出,想要实现观察者设计模式还需要实现 SplObserver 接口。同时,需要实现 SplSubject 接口的三个方法。

下面是 SplObserver 在官方的释义。

SplObserver {
    abstract public void update ( SplSubject $subject )
}

大概的实现如下:

class observer1 implements \SplObserver {
    public function update(\SplSubject $subject) 
    {
        echo 'I\'m observer1;';
    }
}

class observer2 implements \SplObserver {
    public function update(\SplSubject $subject) 
    {
        echo 'I\'m observer2;';
    }
}

class observer3 implements \SplObserver {
    public function update(\SplSubject $subject) 
    {
        echo 'I\'m observer3;';
    }
}

class subject implements \SplSubject {
    protected $observers = [];

    public function attach(\SplObserver $observer) 
    {
        $this->observers[] = $observer;
    }
    
    public function detach(\SplObserver $observer) 
    {
        if ($key = array_search($observer, $this->observers)) {
            unset($this->observers[$key]);
        }
    }
    
    public function notify() 
    {
        $observers = $this->observers;
        foreach ($observers as $observer) {
            $observer->update($this);
        }
    }
}

$observer1Cls = new observer1();
$observer2Cls = new observer2();
$observer3Cls = new observer3();

$subjectCls = new subject();
$subjectCls->attach($observer1Cls);
$subjectCls->attach($observer2Cls);
$subjectCls->attach($observer3Cls);
$subjectCls->notify();

# 输出:I\'m observer1;I\'m observer2;I\'m observer3;

$subjectCls->detach($observer2Cls);
$subjectCls->notify();

# 输出:I\'m observer1;I\'m observer3;

上述的实现方案也是项目中的实现方案,所有的观察者被放在一个类全局的数组中。

一般看手册的时候,会大致看一下人家是怎么使用的。就那么一看,看到了人家的实现方式,和自己有些出入,而且对于观察者的管理不是用的数组,而是用的是 PHP 官方提供的类 SplObjectStorage

下面是官方对于 SplObjectStorage 类的释义:

The SplObjectStorage class provides a map from objects to data or, by ignoring data, an object set. This dual purpose can be useful in many cases involving the need to uniquely identify objects.

SplObjectStorage 类提供从对象到数据的映射,或者通过忽略数据提供对象集。这种双重用途在许多需要唯一标识对象的情况下是有用的。

SplObjectStorage implements Countable , Iterator , Serializable , ArrayAccess {
    public void addAll ( SplObjectStorage $storage )
    public void attach ( object $object [, mixed $data = NULL ] )
    public bool contains ( object $object )
    public int count ( void )
    public object current ( void )
    public void detach ( object $object )
    public string getHash ( object $object )
    public mixed getInfo ( void )
    public int key ( void )
    public void next ( void )
    public bool offsetExists ( object $object )
    public mixed offsetGet ( object $object )
    public void offsetSet ( object $object [, mixed $data = NULL ] )
    public void offsetUnset ( object $object )
    public void removeAll ( SplObjectStorage $storage )
    public void removeAllExcept ( SplObjectStorage $storage )
    public void rewind ( void )
    public string serialize ( void )
    public void setInfo ( mixed $data )
    public void unserialize ( string $serialized )
    public bool valid ( void )
}

通过官网提供的信息,可以初步判断 SplObjectStorage 的使用方法。

下面是 SplSubject 手册中,一位网友提供的 观察者设计模式 的实现方案。

// 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
*/

比起之前使用数组管理观察者的方式,SplSubjectStorage 的管理方式是比较优秀的,至于其他的一些不同和感受,目前没有太明确的感觉。

最后

这篇的篇幅不长,大部分的内容都来自于 PHP 官网,但自己的感触还是蛮深的。

本以为自己已经比较熟悉 PHP 的相关函数了,就算不知道的也是平常不常用的。

可现在感觉不同了,还是有很多好用的,我却忽略的函数和接口在默默奉献。

多看、多记、多思、多练,是提升自己的不二法门。

-- EOF --
本文转载自IMJCW
原文链接:PHP自带的观察者模式接口

相关文章

网友评论

      本文标题:PHP自带的观察者模式接口

      本文链接:https://www.haomeiwen.com/subject/uhgqtqtx.html