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 相关文章推荐
php 图片上添加透明度渐变的效果
Jun 29 PHP
关于PHP5 Session生命周期介绍
Mar 02 PHP
PHP类的静态(static)方法和静态(static)变量使用介绍
Feb 19 PHP
Eclipse中php插件安装及Xdebug配置的使用详解
Apr 25 PHP
PHP解码unicode编码的中文字符代码分享
Aug 13 PHP
php ucwords() 函数将字符串中每个单词的首字符转换为大写(实现代码)
May 12 PHP
php 在字符串指定位置插入新字符的简单实现
Jun 28 PHP
PHP小偷程序的设计与实现方法详解
Oct 15 PHP
php json中文编码为null的解决办法
Dec 14 PHP
PHP常用操作类之通信数据封装类的实现
Jul 16 PHP
PHP通过bypass disable functions执行系统命令的方法汇总
May 02 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
Mar 30 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
打造计数器DIY三步曲(中)
2006/10/09 PHP
PHP5中Cookie与 Session使用详解
2013/04/30 PHP
Yii2框架使用计划任务的方法
2016/05/25 PHP
php基于自定义函数记录log日志方法
2017/07/21 PHP
PHP实现登录验证码校验功能
2018/05/17 PHP
基于jquery的模态div层弹出效果
2010/08/21 Javascript
基于SVG的web页面图形绘制API介绍及编程演示
2013/06/28 Javascript
jquery中交替点击事件的实现代码
2014/02/14 Javascript
文本域中换行符的替换示例
2014/03/04 Javascript
基于jQuery实现动态数字展示效果
2015/08/12 Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
2017/07/02 Javascript
手把手教你搭建ES6的开发运行环境
2017/07/11 Javascript
详解vue项目首页加载速度优化
2017/10/18 Javascript
js操作table中tr的顺序实现上移下移一行的效果
2018/11/22 Javascript
详解Vue前端生产环境发布配置实战篇
2019/05/07 Javascript
js中apply和call的理解与使用方法
2019/11/27 Javascript
vue使用nprogress加载路由进度条的方法
2020/06/04 Javascript
vue flex 布局实现div均分自动换行的示例代码
2020/08/05 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
Python实现从脚本里运行scrapy的方法
2015/04/07 Python
Python中计算三角函数之cos()方法的使用简介
2015/05/15 Python
Python环境下搭建属于自己的pip源的教程
2016/05/05 Python
Python和C/C++交互的几种方法总结
2017/05/11 Python
Python 解决中文写入Excel时抛异常的问题
2018/05/03 Python
Python FTP两个文件夹间的同步实例代码
2018/05/25 Python
PyCharm的设置方法和第一个Python程序的建立
2019/01/16 Python
python中字符串数组逆序排列方法总结
2019/06/23 Python
Django urls.py重构及参数传递详解
2019/07/23 Python
浅谈Pytorch中的torch.gather函数的含义
2019/08/18 Python
python GUI库图形界面开发之PyQt5单行文本框控件QLineEdit详细使用方法与实例
2020/02/27 Python
Python如何生成xml文件
2020/06/04 Python
python 如何把docker-compose.yaml导入到数据库相关条目里
2021/01/15 Python
美国旅游网站:Tours4Fun
2017/02/17 全球购物
员工培训邀请函
2014/01/11 职场文书
双十佳事迹材料
2014/01/29 职场文书
教师自我鉴定范文
2014/03/20 职场文书