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 IP及IP段进行访问限制的代码
Dec 17 PHP
php下使用strpos需要注意 === 运算符
Jul 17 PHP
解析smarty 截取字符串函数 truncate的用法介绍
Jun 20 PHP
计算php页面运行时间的函数介绍
Jul 01 PHP
PHP 输出URL的快捷方式示例代码
Sep 22 PHP
PHP简单的MVC框架实现方法
Dec 01 PHP
php用正则判断是否为数字的方法
Mar 25 PHP
thinkphp整合微信支付代码分享
Nov 24 PHP
php表单文件iframe异步上传实例讲解
Jul 26 PHP
Laravel框架基于ajax实现二级联动功能示例
Jan 17 PHP
PHP实现抽奖功能实例代码
Jun 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
PHP中的float类型使用说明
2010/07/27 PHP
php定义一个参数带有默认值的函数实例分析
2015/03/16 PHP
JavaScript获取多个数组的交集简单实例
2013/11/11 Javascript
Javascript浅谈之this
2013/12/17 Javascript
javascript实现文本域写入字符时限定字数
2014/02/12 Javascript
javascript实现带下拉子菜单的导航菜单效果
2015/05/14 Javascript
jquery实现简洁文件上传表单样式
2015/11/02 Javascript
jQuery+json实现动态创建复杂表格table的方法
2016/10/25 Javascript
基于js实现的限制文本框只可以输入数字
2016/12/05 Javascript
web 屏蔽BackSpace键实例代码
2016/12/24 Javascript
令按钮悬浮在(手机)页面底部的实现方法
2017/05/02 Javascript
underscore之Collections_动力节点Java学院整理
2017/07/10 Javascript
JS笛卡尔积算法与多重数组笛卡尔积实现方法示例
2017/12/01 Javascript
理解 JavaScript EventEmitter
2018/03/29 Javascript
vue系列之requireJs中引入vue-router的方法
2018/07/18 Javascript
jQuery实现简单的Ajax调用功能示例
2019/02/15 jQuery
JS数组扁平化(flat)方法总结详解
2019/06/24 Javascript
使用flow来规范javascript的变量类型
2019/09/12 Javascript
vue3实现v-model原理详解
2019/10/09 Javascript
python中利用zfill方法自动给数字前面补0
2018/04/10 Python
python3实现网络爬虫之BeautifulSoup使用详解
2018/12/19 Python
基于python 凸包问题的解决
2020/04/16 Python
详解使用Python写一个向数据库填充数据的小工具(推荐)
2020/09/11 Python
Fashion Eyewear美国:英国线上设计师眼镜和太阳镜的零售商
2016/08/15 全球购物
优秀生推荐信范文
2013/11/28 职场文书
团日活动总结书
2014/05/08 职场文书
后备干部培训方案
2014/05/22 职场文书
男性健康日的活动方案
2014/08/18 职场文书
2015年入党决心书
2015/02/05 职场文书
护士求职自荐信
2015/03/25 职场文书
关于公司年会的开幕词
2016/03/04 职场文书
python使用openpyxl库读写Excel表格的方法(增删改查操作)
2021/05/02 Python
Python数据分析入门之数据读取与存储
2021/05/13 Python
浅谈Java父子类加载顺序
2021/08/04 Java/Android
python神经网络Xception模型
2022/05/06 Python
uniapp引入支付宝原生扫码插件步骤详解
2022/07/23 Javascript