美文网首页
PHP设计模式之观察者模式

PHP设计模式之观察者模式

作者: 遗失的美好灬 | 来源:发表于2020-08-09 11:04 被阅读0次

#### 使用场景

假设项目经理让我们写了一个登陆接口,咔咔擦擦写完了

- 第二天让我们加入统计登陆次数,然后在后面加代码

- 第三天让我们判断登陆地区,又在后面加代码

- 第四天让我们在用户登陆后推送活动,再再后面加代码

- 第N天,这个接口已经杂乱到没人想维护了

我们需要让项目保持高内聚低耦合,就可以用到观察者模式(也不是非要,看需求)

#### 概念

观察者,观察者,首先要有个被人观察的角色,这是唯一的,然后会有无数个观察者去看她,可以说是一群人在围观一个人,既然有无数个观众,那总得有个东西记录有哪些观察者,那就应该有一个类似于数组一样来储存所有观察者,总结就是一个被观察者,无数个观察者,再有一个容器记录

#### 代码示例

- 接口示例

``` php

// 主题接口

interface Subject{

    public function register(Observer $observer);

    public function notify();

}

// 观察者接口

interface Observer{

    public function watch();

}

```

Subject就是被观察者,Observer就是观众,也就是观察者

### 被观察者

```php

// 被观察者

class Action implements Subject{

    public $_observers=array();

    public function register(Observer $observer){

        $this->_observers[]=$observer;

    }

    public function notify(){

        foreach ($this->_observers as $observer) {

            $observer->watch();

        }

    }

}

```

Action实现了被观察者接口,他现在就是被观察者,再定义一个$_observers数组,他就是记录观众的容器了。

首先实现register方法,用它传入一个观察者,然后塞到数组里,再实现notify()方法,它会遍历容器数组,执行每个观察者的watch()方法。

#### 观察者

```php

// 观察者

class Cat implements Observer{

    public function watch(){

        echo "Cat watches TV<hr/>";

    }

}

class Dog implements Observer{

    public function watch(){

        echo "Dog watches TV<hr/>";

    }

}

class People implements Observer{

    public function watch(){

        echo "People watches TV<hr/>";

    }

}

```

这里定义了三个观察者,全都实现了Observer接口,前面的Subject会循环调用每个观察者的watch()方法,所以我们需要实现每个观察者的watch()方法。

#### 调用

```php

// 应用实例

$action=new Action();

$action->register(new Cat());

$action->register(new People());

$action->register(new Dog());

$action->notify();

```

首先new被观察者对象,执行它的register()方法,把每个观察者都放入容器数组,最后执行notify()方法,通知所有观察者执行自己的方法。

#### PHP原生自带的观察者模式

PHP有自带的观察者模式

- splsubject接口 - 被观察者

- Observer接口 - 观察者

- SplObjectStorage对象 - 容器

首先我们有一个用户登录类

```php

class user{

  public function login()

  {

  echo '登录完毕'

  }

  ```

让他实现splsubject接口成为被观察者。

- 首先在构造函数里,让他new SplObjectStorag()对象并赋值到属性上方便后面调用

- 实现attach()方法,用来注册观察者

- 实现detach()方法,用来删除观察者

- 实现notify()方法,用来遍历容器,调用每个观察者的update方法(必须是update)

- rewind方法是容器指针重置到最开始,valid方法检测容器是否遍历完成并返回布尔,current方法是获取当前的观察者,next方法是将指针后移一位

- 修改login()方法,在里面调用notify()来通知观察者事件完成了

```php

class user implements splsubject{

    protected $observer = null;

    public function __construct()

    {

        $this->observer = new SplObjectStorage();

    }

    public function login()

    {

        $this->notify();

        echo '登录完毕';

    }

    public function attach(SplObserver $observer)

    {

        $this->observer->attach($observer);

    }

    public function detach(SplObserver $observer)

    {

        $this->observer->detach($observer);

    }

    public function notify()

    {

        $this->observer->rewind();

        while ($this->observer->valid())

        {

            $observer = $this->observer->current();

            $observer->update($this);

            $this->observer->next();

        }

    }

}

```

#### 观察者

每个观察者实现SplObserver接口,并实现update()方法

```php

class cat implements SplObserver {

    public function update(SplSubject $subject)

    {

        echo '小猫叫一下';

    }

}

class dog implements SplObserver {

    public function update(SplSubject $subject)

    {

        echo '小狗吼一声';

    }

}

```

#### 应用

```php

// 实时观察

$user = new user();

$user->attach(new cat());

$user->attach(new dog());

$user->login();

```

相关文章

网友评论

      本文标题:PHP设计模式之观察者模式

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