• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

设计模式:观察者模式介绍与应用场景

相关文章 海叔叔 4年前 (2021-11-24) 48次浏览 已收录 0个评论
文章目录[隐藏]

简短描述

在观察者模式中,有一个主题和几个观察者,主题状态改变之后会通知到所有的观察者。

现实中的观察者模式

观察者模式和现实世界很好对应。比如我和我的朋友们购买了今年一年的报纸,每次报社印刷了今天的报纸之后就会往我这里送。在这个系统里面,“报社“是一个主题,“我和我的朋友们”就是一个观察者,当“报社”生产报纸之后,“我和我的朋友们”都能收到这份报纸。
根据上面的描述,我们很容易写出一个观察者模式。首先定义一个报社作为主题,然后定义一些用户作为观察者。不过在此之前,我们先定义主题和观察者的接口,毕竟我们是面向接口编程。

定义一个主题接口

namespace ds\observer\contract;

/**
* 主题接口
*/

interface Subject
{
/**
* 添加一个观察者
* @param Observer $observer
*/
public function add(Observer $observer);
/**
* 移除一个观察者
* @param Observer $observer
* @return boolean
*/
public function remove(Observer $observer);
/**
* 通知所有观察者
* @param mixed $data
* @return boolean
*/
public function notify($data);
}

定义一个观察者接口

namespace ds\observer\contract;

/**
* 观察者
*/
interface Observer
{
/**
* 执行自己的逻辑
* @param mixed $data
* @return boolean
*/
public function execute($data);}

定义报社,实现主题接口

namespace ds\observer;

/**
* 报社主题
*/
class Newspaper implements contract\Subject
{
protected $Observers;

/**
* 添加一个观察者
* @param Observer $observer
*/
public function add(contract\Observer $observer)
{
$hash = $this->hash($observer);
$this->Observers[$hash] = $observer;
}
/**
* 移除一个观察者
* @param Observer $observer
*/
public function remove(contract\Observer $observer)
{
$hash = $this->hash($observer);
unset($this->Observers[$hash]);
}
/**
* 通知所有观察者
* @param mixed $data
* @return boolean
*/
public function notify($data)
{
foreach ($this->Observers as $observer) {
$observer->execute($data);
}
}

protected function hash($obj)
{
return spl_object_hash($obj);
}
}

定义用户,实现观察者接口

namespace ds\observer;

/**
* 用户
*/
class User implements contract\Observer
{
public function __construct($name)
{
$this->name = $name;
}

/**
* 执行观察者自身逻辑
* @param string $data
* @return void
*/
public function execute($data)
{
echo $this->name . "收到了" . $data . "\n";
}

public function attach(contract\Subject $subject)
{
$subject->add($this);
}}

执行主流程

到目前位置,我们创建了主题-报社、观察者-用户,他们分别实现了相应的接口,看起来一切准备就绪了。接着这些代码就可以跑起来了。

namespace ds\observer;

require __DIR__ . '/contract/Observer.php';
require __DIR__ . '/contract/Subject.php';
require __DIR__ . '/Newspaper.php';
require __DIR__ . '/User.php';

// 创建一个新的报社
$newspaper = new Newspaper();

// 创建一个新的用户cmhc
$cmhc = new User('cmhc');
// 让这个用户去订阅这个报纸
$cmhc->attach($newspaper);

// 再创建一个用户xiaoming
$xiaoming = new User('xiaoming');
// 让xiaoming也订阅这个报社
$xiaoming->attach($newspaper);

// 报社今天发布了一个观察者模式,通知一下订阅我的人
$newspaper->notify('《设计模式之观察者模式》');

如果执行上面的代码,你会得到如下结果:

cmhc收到了《设计模式之观察者模式》
xiaoming收到了《设计模式之观察者模式》

可能很多人都知道观察者模式,也知道观察者模式要怎么去实现,但是却找不到具体的业务场景去使用它。但实际上观察者模式的应用是十分广泛的。下面就介绍几个经常使用观察者模式的几个场景

支付场景

在支付场景下,用户购买一件商品,当支付成功之后三方会回调自身,在这个时候系统可能会有很多需要执行的逻辑(如:更新订单状态,发送邮件通知,赠送礼品…),这些逻辑之间并没有强耦合,因此天然适合使用观察者模式去实现这些功能,当有更多的操作时,只需要添加新的观察者就能实现,完美实现了对修改关闭,对扩展开放的开闭原则。

UGC场景

在一个UGC场景下,用户发布的内容往往会经过很多流程,大部分是先发往审核系统,当审核通过之后就会出现一系列的业务逻辑,比如更新内容状态,通知给所有的粉丝等等。


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:设计模式:观察者模式介绍与应用场景
喜欢 (3)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址