attach.php,PHP 设计模式 - 行为型 - 观察者模式(Observer)

1. 模式定义

观察者模式有时也被称作发布/订阅模式,该模式用于为对象实现发布/订阅功能:一旦主体对象状态发生改变,与之关联的观察者对象会收到通知,并进行相应操作。

将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。 消息队列系统、事件都使用了观察者模式。

PHP 为观察者模式定义了两个接口:SplSubject 和 SplObserver。SplSubject 可以看做主体对象的抽象,SplObserver 可以看做观察者对象的抽象,要实现观察者模式,只需让主体对象实现 SplSubject ,观察者对象实现 SplObserver,并实现相应方法即可。

2. UML类图

722f11fdda68

image.png

3. 示例代码

User.php 实现SplSubject的对象

namespace DesignPattern\Behavioral\Observer;

use SplObserver;

/**

* 观察者模式 : 被观察对象 (主体对象)

*

* 主体对象维护观察者列表并发送通知

*

*/

class User implements \SplSubject

{

/**

* 用户数据

*

* @var array

*/

protected $data = array();

/**

* 观察者对象集

*

* @var \SplObjectStorage

*/

protected $observers;

public function __construct()

{

$this->observers = new \SplObjectStorage();

}

/**

* 附加观察者

* @link https://php.net/manual/en/splsubject.attach.php

* @param SplObserver $observer

* The SplObserver to attach.

*

* @return void

* @since 5.1.0

*/

public function attach(SplObserver $observer)

{

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

}

/**

* 取消观察者

* @link https://php.net/manual/en/splsubject.detach.php

* @param SplObserver $observer

* The SplObserver to detach.

*

* @return void

* @since 5.1.0

*/

public function detach(SplObserver $observer)

{

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

}

/**

* 通知观察者此用户进行更新

* @link https://php.net/manual/en/splsubject.notify.php

* @return void

* @since 5.1.0

*/

public function notify()

{

/** @var \SplObserver $observer */

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

$observer->update($this);

}

}

/**

*

* 设置/更新用户数据

* @param string $name

* @param mixed $value

*

* @return void

*/

public function __set($name, $value)

{

$this->data[$name] = $value;

// 通知观察者用户被改变

$this->notify();

}

}

UserObserver.php 实现SplObserver的对象

namespace DesignPattern\Behavioral\Observer;

use SplSubject;

class UserObserver implements \SplObserver

{

/**

* 收到观察对象被更新的消息,进行操作

* @link https://php.net/manual/en/splobserver.update.php

* @param SplSubject $subject

* 这个 SplSubject通知观察者更新

*

* @return void

* @since 5.1.0

*/

public function update(SplSubject $subject)

{

echo get_class($subject) . ' 被更新';

}

}

单元测试

namespace DesignPattern\Tests;

use DesignPattern\Behavioral\Observer\User;

use DesignPattern\Behavioral\Observer\UserObserver;

use PHPUnit\Framework\TestCase;

/**

* 观察者模式测试

* Class ObserverTest

* @package DesignPattern\Tests

*/

class ObserverTest extends TestCase

{

protected $observer;

protected function setUp(): void

{

$this->observer = new UserObserver();

}

/**

* 测试通知

*/

public function testNotify()

{

$this->expectOutputString('DesignPattern\Behavioral\Observer\User 被更新');

$subject = new User();

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

$subject->property = 123;

}

/**

* 测试订阅

*/

public function testAttachDetach()

{

$subject = new User();

$reflection = new \ReflectionProperty($subject, 'observers');

$reflection->setAccessible(true);

/** @var \SplObjectStorage $observers */

$observers = $reflection->getValue($subject);

$this->assertInstanceOf('SplObjectStorage', $observers);

$this->assertFalse($observers->contains($this->observer));

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

$this->assertTrue($observers->contains($this->observer));

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

$this->assertFalse($observers->contains($this->observer));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值