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 相关文章推荐
session 的生命周期是多长
Oct 09 PHP
PHP如何透过ODBC来存取数据库
Oct 09 PHP
dedecms采集中可以过滤多行代码的正则表达式
Mar 17 PHP
php的正则处理函数总结分析
Jun 20 PHP
php 数组的一个悲剧?
May 11 PHP
php引用传值实例详解学习
Nov 06 PHP
PHP set_error_handler()函数使用详解(示例)
Nov 12 PHP
php中Y2K38的漏洞解决方法实例分析
Sep 22 PHP
php实现字符串翻转的方法
Mar 27 PHP
浅谈PHP的反射API
Feb 26 PHP
PDO::inTransaction讲解
Jan 28 PHP
浅谈Laravel中使用Slack进行异常通知
May 29 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
基于Discuz security.inc.php代码的深入分析
2013/06/03 PHP
php给一组指定关键词添加span标签的方法
2015/03/31 PHP
PHP实现负载均衡的加权轮询方法分析
2018/08/22 PHP
Jquery插件之打造自定义的select标签
2011/11/30 Javascript
按Enter键触发事件的jquery方法实现代码
2014/02/17 Javascript
jQuery实现点击图片翻页展示效果的方法
2015/02/16 Javascript
jQuery Html控件基本操作(日常收集整理)
2016/03/11 Javascript
Extjs4.0 ComboBox如何实现三级联动
2016/05/11 Javascript
前端自动化开发之Node.js的环境搭建教程
2017/04/01 Javascript
jQuery+C#实现参数RSA加密传输功能【附jsencrypt.js下载】
2017/06/26 jQuery
基于jQuery Easyui实现登陆框界面
2017/07/10 jQuery
React Native第三方平台分享的实例(Android,IOS双平台)
2017/08/04 Javascript
weebox弹出窗口不居中显示的解决方法
2017/11/27 Javascript
Vue通过URL传参如何控制全局console.log的开关详解
2017/12/07 Javascript
vue列表单项展开收缩功能之this.$refs的详解
2019/05/05 Javascript
JS中的一些常用的函数式编程术语
2019/06/15 Javascript
微信小程序实现拖拽功能
2019/09/26 Javascript
webpack打包html里面img后src为“[object Module]”问题
2019/12/22 Javascript
PYTHON正则表达式 re模块使用说明
2011/05/19 Python
为什么你还不懂得怎么使用Python协程
2019/05/13 Python
pandas的排序和排名的具体使用
2019/07/31 Python
Python文件操作函数用法实例详解
2019/12/24 Python
Python 读取xml数据,cv2裁剪图片实例
2020/03/10 Python
Django数据结果集序列化并展示实现过程
2020/04/22 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
详解python的变量缓存机制
2021/01/24 Python
css3弹性盒模型(Flexbox)详细介绍
2014/10/08 HTML / CSS
马来西亚最好的婴儿商店:Motherhood
2017/09/14 全球购物
DNA测试:Orig3n
2019/03/01 全球购物
内部类的定义、种类以及优点
2013/10/16 面试题
学校经典推荐信
2013/10/30 职场文书
行政人事岗位职责
2014/03/17 职场文书
保护环境倡议书100字
2014/05/19 职场文书
个人校本研修方案
2014/05/26 职场文书
领导班子三严三实心得体会
2014/10/13 职场文书
Java虚拟机内存结构及编码实战分享
2022/04/07 Java/Android