PHP设计模式之观察者模式实例


Posted in PHP onFebruary 22, 2016

首先了解观察者模式的概念:一个对象通过添加一个方法(该方法允许另一个对象,即观察者 注册自己)使本身变得可观察。当可观察的对象更改时,它会将消息发送到已注册的观察者。这些观察者使用该信息执行的操作与可观察的对象无关。结果是对象可以相互对话,而不必了解原因。观察者模式是一种事件系统,意味着这一模式允许某个类观察另一个类的状态,当被观察的类状态发生改变的时候,观察类可以收到通知并且做出相应的动作;观察者模式为您提供了避免组件之间紧密耦。

UML结构图:

PHP设计模式之观察者模式实例

观察者模式解决的问题

在我们的开发过程中,应该都或多或少的碰到过改动其中一部分代码会引起其他一连串改变的问题,显然想要完全避免这种情况不太可能,但我们也应答尽量减少对其他组件的依赖,而观察者模式就是为了解决这个问题。

举个例子来说,我们有一个帖子对象,代码如下:

class Post
{
protected $_userid = null;
protected $_ip = null;
protected $_content = null;
function __construct()
{
// ...
}
// 发帖方法
public function addPost()
{
// ... 发帖逻辑
}
}

在上面是一个普通的帖子对象,随着发帖量和访问量越来越大,运营们开始不干了,公司也经常会接到投诉电话,说我们的网站有许多敏感内容和垃圾广告,因此我们需要做内容审核:首先是对用户的审核,一些黑名单用户应该被禁止发帖;二是对IP的审核;三是对内容敏感词的审核。因此我们的代码就成了如下的样子:

class Post
{
protected $_userid = null;
protected $_ip = null;
protected $_content = null;
function __construct()
{
}
public function addPost()
{
if (!Postscan::checkUserid($tihs->_userid)) {
return false;
}
if (!Postscan::ipUserid($tihs->_ip)) {
return false;
}
if (!Postscan::checkContent($tihs->_content)) {
return false;
}
// ... 
}
}

随着需要审核的字段越来越多,addPost方法变得越来越长,发布对象被也只能紧紧的被嵌入到该系统中。

观察者模式的实现

观察者模式的核心是把观察者从主体中分离开来,当主体知道事件发生时,观察需要被通知到,同时我们也不想把主体和观察者之间的关系写死,于是我们来修改下我们上面的代码:

//主体必须实现的接口
interface Observable {
public function attach(Observer $observer);
public function detach(Observer $observer);
public function notify();
}
//观察者必须实现的接口
interface Observer {
public function do(Observable $subject);
}
class Post implements Observable
{
protected $_userid = null;
protected $_ip = null;
protected $_content = null;
protected $_observerlist = array();
function __construct()
{
}
public function attach(Observer $observer)
{
$this->_observerlist[] = $observer;
}
public function detach(Observer $observer)
{
foreach ($this->_observerlist as $key => $value) {
if ($observer === $value) {
unset($this->_observerlist[$key])
}
}
}
public function notify()
{
foreach ($this->_observerlist as $value) {
if (!$value->do($this)) {
return false;
}
}
return true;
}
public function addPost()
{
if (!$this->notify()) {
return false;
}
// ... 
}
}

通过上面的代码,我们可以再很容易的加入审核规则。

SPL代码

观察者模式是一个很常见和常用的设计模式,以至于SPL扩展已经为我们封装好了对应的类和方法,下面的代码是根据SPL提供的3个元素:SplObserver,SplSubject,SplObjectStorage来实现的代码

class Post implements SplSubject
{
protected $_userid = null;
protected $_ip = null;
protected $_content = null;
protected $_storage = new SplObjectStorage();
function __construct()
{
}
public function attach(SplObject $observer)
{
$this->_storage->attach($observer);
}
public function detach(SplObject $observer)
{
$this->_storage->detach($observer);
}
public function notify()
{
foreach ($this->_storage as $value) {
if (!$value->update($this)) {
return false;
}
}
return true;
}
public function addPost()
{
if (!$this->notify()) {
return false;
}
// ... 
}
}

很简单吧,最重要的是理解,在这个例子中,我们把一些审核的方法从帖子类中剥离了开来,而且该帖子对象也可以用来作为其他的发布类型。

以上内容实现是小编给大家介绍的PHP设计模式之观察者模式,希望对大家有所帮助!

PHP 相关文章推荐
隐藏X-Space个人空间下方版权方法隐藏X-Space个人空间标题隐藏X-Space个人空间管理版权方法
Feb 22 PHP
php下连接ftp实现文件的上传、下载、删除文件实例代码
Jun 03 PHP
PHP迅雷、快车、旋风下载专用链转换代码
Jun 15 PHP
PHP Cookie的使用教程详解
Jun 03 PHP
基于PHP+Ajax实现表单验证的详解
Jun 25 PHP
CURL状态码列表(详细)
Jun 27 PHP
PHP延迟静态绑定示例分享
Jun 22 PHP
php事务处理实例详解
Jul 11 PHP
php生成唯一数字id的方法汇总
Nov 18 PHP
PHP的Yii框架中Model模型的学习教程
Mar 29 PHP
Ajax提交表单时验证码自动验证 php后端验证码检测
Jul 20 PHP
php验证码生成器
May 24 PHP
PHP编写RESTful接口的方法
Feb 21 #PHP
PHP常见漏洞攻击分析
Feb 21 #PHP
php采集神器cURL使用方法详解
Feb 19 #PHP
PHP 使用 Imagick 裁切/生成缩略图/添加水印自动检测和处理 GIF
Feb 19 #PHP
PHP利用imagick生成组合缩略图
Feb 19 #PHP
对比分析php中Cookie与Session的异同
Feb 19 #PHP
php强大的时间转换函数strtotime
Feb 18 #PHP
You might like
用缓存实现静态页面的测试
2006/12/06 PHP
主流PHP框架的优缺点对比分析
2014/12/25 PHP
jQuery 过滤not()与filter()实例代码
2012/05/10 Javascript
js的匿名函数使用介绍
2013/12/11 Javascript
js常用数组操作方法简明总结
2014/06/20 Javascript
JavaScript判断表单提交时哪个radio按钮被选中的方法
2015/03/21 Javascript
AngularJS利用Controller完成URL跳转
2016/08/09 Javascript
Easyui Tree获取当前选择节点的所有顶级父节点
2017/02/14 Javascript
NodeJS配置HTTPS服务实例分享
2017/02/19 NodeJs
Ionic + Angular.js实现图片轮播的方法示例
2017/05/21 Javascript
vue插件开发之使用pdf.js实现手机端在线预览pdf文档的方法
2018/07/12 Javascript
快速了解Node中的Stream流是什么
2019/02/13 Javascript
如何解决js函数防抖、节流出现的问题
2019/06/17 Javascript
javascript实现电商放大镜效果
2020/11/23 Javascript
Python字符串特性及常用字符串方法的简单笔记
2016/01/04 Python
python读取与写入csv格式文件的示例代码
2017/12/16 Python
win10下tensorflow和matplotlib安装教程
2018/09/19 Python
Python实现的文轩网爬虫完整示例
2019/05/16 Python
python实现共轭梯度法
2019/07/03 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
Pandas 缺失数据处理的实现
2019/11/04 Python
python 遗传算法求函数极值的实现代码
2020/02/11 Python
Python API 操作Hadoop hdfs详解
2020/06/06 Python
Python字符串格式化常用手段及注意事项
2020/06/17 Python
基于HTML5的WebGL经典3D虚拟机房漫游动画
2017/11/15 HTML / CSS
Canvas高级路径操作之拖拽对象的实现
2019/08/05 HTML / CSS
Perfume’s Club美国官网:西班牙第一家在线美容店
2020/06/10 全球购物
应届生程序员求职信
2013/11/05 职场文书
暑期社会实践感言
2014/02/25 职场文书
《泉水》教学反思
2014/04/11 职场文书
财务管理专业自荐书
2014/09/02 职场文书
领导欢迎词致辞
2015/01/23 职场文书
WordPress多语言翻译插件 - WPML使用教程
2021/04/01 PHP
用Python提取PDF表格的方法
2021/04/11 Python
MySql 8.0及对应驱动包匹配的注意点说明
2021/06/23 MySQL
Python中itertools库的四个函数介绍
2022/04/06 Python