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程序的php代码
Apr 07 PHP
php下mysql数据库操作类(改自discuz)
Jul 03 PHP
PHP新手用的Insert和Update语句构造类
Mar 31 PHP
php中使用接口实现工厂设计模式的代码
Jun 17 PHP
解析:通过php socket并借助telnet实现简单的聊天程序
Jun 18 PHP
PHP文件缓存内容保存格式实例分析
Aug 20 PHP
php实现上传图片保存到数据库的方法
Feb 11 PHP
php递归删除指定文件夹的方法小结
Apr 20 PHP
Apache连接PHP后无法启动问题解决思路
Jun 18 PHP
thinkPHP模板引擎用法示例
Dec 08 PHP
PHP简单实现循环链表功能示例
Nov 10 PHP
Laravel的加密解密与哈希实例讲解
Mar 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
基于PHP常用字符串的总结(待续)
2013/06/07 PHP
php时间戳格式化显示友好的时间函数分享
2014/10/21 PHP
php编程每天必学之表单验证
2016/03/01 PHP
thinkphp查询,3.X 5.0方法(亲试可行)
2017/06/17 PHP
javascript之学会吝啬 精简代码
2010/04/25 Javascript
JQuery 操作select标签实现代码
2010/05/14 Javascript
JavaScript Tips 使用DocumentFragment加快DOM渲染速度
2010/06/28 Javascript
Jquery.addClass始终无效原因分析
2013/09/08 Javascript
使用apply方法实现javascript中的对象继承
2013/12/16 Javascript
jQuery中size()方法用法实例
2014/12/27 Javascript
JavaScript实现iframe自动高度调整和不同主域名跨域
2016/02/27 Javascript
js实现精确到秒的日期选择器完整实例
2016/04/30 Javascript
javascript表单事件处理方法详解
2016/05/15 Javascript
JQuery EasyUI的一些常用组件
2017/07/12 jQuery
JS运动特效之任意值添加运动的方法分析
2018/01/24 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
vue+vue-router转场动画的实例代码
2018/09/01 Javascript
JavaScript基础教程之如何实现一个简单的promise
2018/09/11 Javascript
JQuery 实现文件下载的常用方法分析
2019/10/29 jQuery
vue实例的选项总结
2020/06/09 Javascript
在vue中使用Echarts利用watch做动态数据渲染操作
2020/07/20 Javascript
Python连接mssql数据库编码问题解决方法
2015/01/01 Python
解决python3中自定义wsgi函数,make_server函数报错的问题
2017/11/21 Python
Python实现冒泡排序的简单应用示例
2017/12/11 Python
Django CBV类的用法详解
2019/07/26 Python
详解CSS3伸缩布局盒模型Flex布局
2018/08/20 HTML / CSS
浅谈html5 video 移动端填坑记
2018/01/15 HTML / CSS
玩具反斗城葡萄牙官方商城:Toys"R"Us葡萄牙
2016/10/21 全球购物
娇韵诗俄罗斯官方网站:Clarins俄罗斯
2020/10/03 全球购物
基层党组织建设整改方案
2014/09/16 职场文书
党的群众路线教育实践活动学习计划
2014/11/03 职场文书
卡特教练观后感
2015/06/08 职场文书
四风之害观后感
2015/06/09 职场文书
电影雷锋观后感
2015/06/10 职场文书
三年级作文之趣事作文
2019/11/04 职场文书
Mysql中where与on的区别及何时使用详析
2021/08/04 MySQL