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 相关文章推荐
PHP4(windows版本)中的COM函数
Oct 09 PHP
一步一步学习PHP(5) 类和对象
Feb 16 PHP
php class中public,private,protected的区别以及实例分析
Jun 18 PHP
destoon整合ucenter后注册页面不跳转的解决方法
Jun 21 PHP
ThinkPHP多语言支持与多模板支持概述
Aug 22 PHP
PHP Header失效的原因分析及解决方法
Nov 16 PHP
PHP屏蔽关键字实现方法
Nov 17 PHP
PHP中大括号'{}'用法实例总结
Feb 08 PHP
PHP编程计算日期间隔天数的方法
Apr 26 PHP
PHP批量删除jQuery操作
Jul 23 PHP
laravel框架模型、视图与控制器简单操作示例
Oct 10 PHP
PHP图像处理 imagestring添加图片水印与文字水印操作示例
Feb 06 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
php微信公众开发之获取周边酒店信息的方法
2014/12/22 PHP
简单的pgsql pdo php操作类实现代码
2016/08/25 PHP
jquery 批量上传图片实现代码
2010/01/28 Javascript
jQuery1.6 使用方法一
2011/11/23 Javascript
密码强度检测效果实现原理与代码
2013/01/04 Javascript
判断javascript的数据类型(示例代码)
2013/12/11 Javascript
JavaScript eval() 函数介绍及应用示例
2014/07/29 Javascript
jQuery中DOM操作实例分析
2015/01/23 Javascript
JQuery显示、隐藏div的几种方法简明总结
2015/04/16 Javascript
深入理解JavaScript中的对象
2015/06/04 Javascript
基于JavaScript操作DOM常用的API小结
2015/12/01 Javascript
深入浅析JavaScript中with语句的理解
2016/05/12 Javascript
js css自定义分页效果
2017/02/24 Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
2017/04/13 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
微信小程序实现滑动切换自定义页码的方法分析
2018/12/29 Javascript
JavaScript函数式编程(Functional Programming)高阶函数(Higher order functions)用法分析
2019/05/22 Javascript
elementui之el-tebs浏览器卡死的问题和使用报错未注册问题
2019/07/06 Javascript
vue实现的封装全局filter并统一管理操作示例
2020/02/02 Javascript
vue实现几秒后跳转新页面代码
2020/09/09 Javascript
[58:29]DOTA2-DPC中国联赛 正赛 Phoenix vs XG BO3 第一场 1月31日
2021/03/11 DOTA
python函数装饰器用法实例详解
2015/06/04 Python
利用Python获取操作系统信息实例
2016/09/02 Python
Python中的浮点数原理与运算分析
2017/10/12 Python
把csv文件转化为数组及数组的切片方法
2018/07/04 Python
python语言元素知识点详解
2019/05/15 Python
python对常见数据类型的遍历解析
2019/08/27 Python
导入tensorflow:ImportError: libcublas.so.9.0 报错
2020/01/06 Python
Python动态导入模块和反射机制详解
2020/02/18 Python
多视角3D逼真HTML5水波动画
2016/03/03 HTML / CSS
惠普加拿大在线商店:HP加拿大
2017/09/15 全球购物
会计实习生自我鉴定
2013/12/12 职场文书
高级工程师岗位职责
2013/12/15 职场文书
电焊工工作岗位职责
2014/02/06 职场文书
转预备党员政审材料
2014/02/06 职场文书
群众路线个人对照检查材料
2014/09/23 职场文书