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 相关文章推荐
vBulletin HACK----显示话题大小和打开新窗口于论坛索引页
Oct 09 PHP
实用函数2
Nov 08 PHP
php jquery 实现新闻标签分类与无刷新分页
Dec 18 PHP
初次接触php抽象工厂模式(Elgg)
Mar 21 PHP
PHP pathinfo()获得文件的路径、名称等信息说明
Sep 13 PHP
基于PHP字符串的比较函数strcmp()与strcasecmp()的使用详解
May 15 PHP
获取PHP警告错误信息的解决方法
Jun 03 PHP
解析php中heredoc的使用方法
Jun 17 PHP
php文件压缩之PHPZip类用法实例
Jun 18 PHP
老生常谈ThinkPHP中的行为扩展和插件(推荐)
May 05 PHP
PHP根据key删除数组中指定的元素
Feb 28 PHP
ThinkPHP 5.1 跨域配置方法
Oct 11 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作的文本留言本的例子(二)
2006/10/09 PHP
PHP闭包(Closure)使用详解
2013/05/02 PHP
详解PHP中的PDO类
2015/07/06 PHP
实例讲解PHP中使用命名空间
2019/01/27 PHP
JavaScript CSS修改学习第六章 拖拽
2010/02/19 Javascript
Javascript笔记一 js以及json基础使用说明
2010/05/22 Javascript
用js实现的模拟jquery的animate自定义动画(2.5K)
2010/07/20 Javascript
document.all的一个比较完整的总结及案例
2013/01/31 Javascript
$.getJSON在IE下失效的原因分析及解决方法
2013/06/16 Javascript
nodejs npm install全局安装和本地安装的区别
2014/06/05 NodeJs
javascript异步编程代码书写规范Promise学习笔记
2015/02/11 Javascript
JavaScript中instanceof运算符的使用示例
2016/06/08 Javascript
JavaScript简单下拉菜单特效
2016/09/13 Javascript
angularjs实现下拉列表的选中事件示例
2017/03/03 Javascript
jQuery EasyUI结合zTree树形结构制作web页面
2017/09/01 jQuery
vue mint-ui 实现省市区街道4级联动示例(仿淘宝京东收货地址4级联动)
2017/10/16 Javascript
vue实现全屏滚动效果(非fullpage.js)
2020/03/07 Javascript
es6函数之严格模式用法实例分析
2020/03/17 Javascript
JavaScript自定义超时API代码实例
2020/04/30 Javascript
Python函数嵌套实例
2014/09/23 Python
Python编程中的异常处理教程
2015/08/21 Python
Python实现图片转字符画的代码实例
2019/02/22 Python
windows下安装Python虚拟环境virtualenvwrapper-win
2019/06/14 Python
python如何进行矩阵运算
2020/06/05 Python
keras实现图像预处理并生成一个generator的案例
2020/06/17 Python
python中requests模拟登录的三种方式(携带cookie/session进行请求网站)
2020/11/17 Python
HTML5语义化元素你真的用对了吗
2019/08/22 HTML / CSS
纽约现代艺术博物馆商店:MoMA STORE(室内家具和杂货商品)
2016/08/02 全球购物
墨西哥巴士车票在线购买:ClickBus
2018/03/27 全球购物
请写出一段Python代码实现删除一个list里面的重复元素
2015/12/29 面试题
自主实习接收函
2014/01/13 职场文书
普通党员自我剖析材料
2014/10/07 职场文书
单位接收函格式
2015/01/30 职场文书
春节慰问简报
2015/07/21 职场文书
初中班干部工作总结
2015/08/10 职场文书
python - asyncio异步编程
2021/04/06 Python