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 相关文章推荐
一个简易需要注册的留言版程序
Oct 09 PHP
PHP has encountered an Access Violation
Jan 15 PHP
php调用mysql存储过程实例分析
Dec 29 PHP
smarty模板引擎从配置文件中获取数据的方法
Jan 22 PHP
cakephp打印sql语句的方法
Feb 13 PHP
PHP使用mysql_fetch_row查询获得数据行列表的方法
Mar 18 PHP
Yii快速入门经典教程
Dec 28 PHP
php基于dom实现的图书xml格式数据示例
Feb 03 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
Mar 14 PHP
使用swoole 定时器变更超时未支付订单状态的解决方案
Jul 24 PHP
php将字符串转换为数组实例讲解
May 05 PHP
laravel入门知识点整理
Sep 15 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
CI框架安全类Security.php源码分析
2014/11/04 PHP
php+curl 发送图片处理代码分享
2015/07/09 PHP
php微信公众平台开发(四)回复功能开发
2016/12/06 PHP
根据对象的某一属性进行排序的js代码(如:name,age)
2010/08/10 Javascript
客户端 使用XML DOM加载json数据的方法
2010/09/28 Javascript
Jquery中使用setInterval和setTimeout的方法
2013/04/08 Javascript
原生JS实现响应式瀑布流布局
2015/04/02 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
js实现瀑布流的三种方式比较
2020/06/28 Javascript
使用getBoundingClientRect方法实现简洁的sticky组件的方法
2016/03/22 Javascript
jQuery简单实现遍历单选框的方法
2017/03/06 Javascript
如何在微信小程序中实现Mixins方案
2019/06/20 Javascript
jQuery中DOM常见操作实例小结
2019/08/01 jQuery
15 分钟掌握vue-next响应式原理
2019/10/13 Javascript
微信小程序图片加载失败时替换为默认图片的方法
2019/12/09 Javascript
Nuxt的路由配置和参数传递方式
2020/11/06 Javascript
Python中使用ConfigParser解析ini配置文件实例
2014/08/30 Python
编写同时兼容Python2.x与Python3.x版本的代码的几个示例
2015/03/30 Python
Pandas之drop_duplicates:去除重复项方法
2018/04/18 Python
python实现数据导出到excel的示例--普通格式
2018/05/03 Python
Python实现二维曲线拟合的方法
2018/12/29 Python
Python实现将HTML转成PDF的方法分析
2019/05/04 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
2019/11/15 Python
Python集成开发工具Pycharm的安装和使用详解
2020/03/18 Python
Python RabbitMQ实现简单的进程间通信示例
2020/07/02 Python
Python从文件中读取数据的方法步骤
2020/11/18 Python
Pandas数据分析的一些常用小技巧
2021/02/07 Python
Hobbs官方网站:英国奢华女性时尚服装
2020/02/22 全球购物
毕业生求职简历中的自我评价
2013/10/18 职场文书
爱祖国爱家乡演讲稿
2014/09/02 职场文书
2014中学教师节广播稿
2014/09/10 职场文书
先进事迹材料怎么写
2014/12/30 职场文书
大学生干部培训心得体会
2016/01/06 职场文书
Java输出Hello World完美过程解析
2021/06/13 Java/Android
Python中time标准库的使用教程
2022/04/13 Python
python井字棋游戏实现人机对战
2022/04/28 Python