博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编程中的那些套路——关于观察者模式
阅读量:6836 次
发布时间:2019-06-26

本文共 2677 字,大约阅读时间需要 8 分钟。

该文章属于系列,并且以下内容基于语言PHP

今天我们来谈谈观察者模式,这是一个经常用到的设计模式。

让我们想象一个场景:一个网站有不同等级区域的用户,不同等级的的用户登录后可以获得对应的服务(一级用户登录后获得一级服务,二级用户登录后获得二级服务,…以此类推)。那么我们如何写这段业务逻辑呢?

按照一般思路:我们会写N个if..else判断,像下面这样:

//登录操作..省略 if(一级用户) { echo ' 一级服务'; } else if(二级用户){ echo '二级服务'; } else if(三级用户){ echo '三级服务'; }

但这样写代码有一个弊端,如果我们又增加了一个等级用户,那么我们是不是要修改原来的代码呢(增加多一个if..else判断),这样做是非常不妥当的,因为写好的代码我们不应该碰它。

我们应该写一段拓展性强与维护性较强的代码,由此衍生出观察者模式。

观察者模式的大致思路是这样的:有一个观察者列表(A),有一个被观察者列表(B),当B发生变化时,程序就会遍历观察者列表A,随之执行对应的update操作,然后获得想要的效果。语言表述可能比较难以理解,我们来看代码吧。

PHP已经帮我们内置了一个观察者模式的接口(The SplSubject interface),我们可以直接实现这个接口:

图片描述

并且php还提供了一个存储对象的class(即观察者列表):

图片描述

当然我们完全可以不使用这个类,可以用数组代替。

具体代码:

观察者模式.php

observers = new SplObjectStorage(); } //登录 public function login(){ //登录过程,省略 $this->notify(); } //添加观察者 public function attach(SplObserver $observer){ $this->observers->attach($observer); } //剔除观察者 public function detach(SplObserver $observer){ $this->observers->detach($observer); } //登陆后通知notify public function notify(){ $observers = $this->observers; //这段rewind不可或缺... 将节点指针指向第一位节点 $observers->rewind(); //当前节点存在 while($observers->valid()){ $observer = $observers->current();//获取当前节点(即观察者) $observer->update($this);//进行update犯法操作 $observers->next();//next 节点 } } } //observer User1Observers class User1Observers implements SplObserver { public function update(SplSubject $subject){ echo '我是一级用户,请给我对应的一级服务'; } } //observer User2Observers class User2Observers implements SplObserver { public function update(SplSubject $subject){ echo '我是二级用户,请给我对应的二级服务'; } } //observer CommenUserObservers class CommenUserObservers implements SplObserver { public function update(SplSubject $subject){ echo '我是普通用户,请给我对应的普通服务'; } } //如果需要的话可以继续增加或者减少用户等级,丝毫不会影响原本的等级用户 $subject = new LoginSubject(); $CommenUserObservers = new CommenUserObservers;//普通用户 $subject->attach(new User1Observers);//增加观察者:一级用户 $subject->attach(new User2Observers);//增加观察者:二级用户 $subject->attach($CommenUserObservers);//增加观察者:普通用户 $subject->login();//登录,触发notify //output:我是一级用户,请给我对应的一级服务我是二级用户,请给我对应的二级服务我是普通用户,请给我对应的普通服务 echo '
'; //如果有一天普通用户压根没有对应的服务了,那么我们就可以剔除它了 //$subject->detach(new CommenUserObservers); 无效 $subject->detach($CommenUserObservers);//删除观察者:普通用户 $subject->login();//登录,触发notify,普通用户就不会被通知啦 //output:我是一级用户,请给我对应的一级服务我是二级用户,请给我对应的二级服务 ?>

看出门道了吗?每当登录操作的时候,就会顺带触发notify方法,从而遍历关注者列表内的对象方法update,从而达到不同的用户获得不同的服务目的,而当我们需要新增/减少用户等级的时候又不需要修改源代码,很好的符合了开放封闭原则。

我一直认为观察者模式、、三者都是很棒的设计模式,但观察者模式理解起来稍微比较困难,如果有困惑的话可以直接在评论区发问。

转载地址:http://bsxkl.baihongyu.com/

你可能感兴趣的文章
HTTP Header简介
查看>>
Java并发编程----阻塞队列
查看>>
极简教程: 使用 matplotlib 绘制 GIF 动图
查看>>
数据库分片(Database Sharding)详解
查看>>
技术风险防控平台:打造金融交易系统的故障免疫能力
查看>>
怎样把酷狗音乐wav转化成高品质的MP3格式?
查看>>
浅谈算法学习
查看>>
前端知识点——图片
查看>>
thinkphp源码分析(三)—自动加载篇(Loader的分析)
查看>>
Blink 真香
查看>>
一块听听:Mixin 主网上线语音直播文字稿
查看>>
brew安装错误brew Error: /usr/local must be writable!
查看>>
可应用于实际的14个NLP突破性研究成果(三)
查看>>
[LeetCode] 41. First Missing Positive
查看>>
阿里如何将“高峰前扩容、高峰后缩容”的梦想照进现实?
查看>>
分布式系统关注点——初识「高可用」
查看>>
Node.js学习之路22——利用cheerio制作简单的网页爬虫
查看>>
聊一聊我对 React Context 的理解以及应用
查看>>
很多程序员都不会的问题,你知道多少?
查看>>
Scrapy-redis分布式组件
查看>>