摘要:我们应该写一段拓展性强与维护性较强的代码,由此衍生出观察者模式。
该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言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,从而达到不同的用户获得不同的服务目的,而当我们需要新增/减少用户等级的时候又不需要修改源代码,很好的符合了开放封闭原则。
我一直认为观察者模式、单例模式、工厂模式三者都是很棒的设计模式,但观察者模式理解起来稍微比较困难,如果有困惑的话可以直接在评论区发问。
该文章属于《编程中的那些经典套路——设计模式汇总》系列
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/21671.html
该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 今天来谈谈责任链模式,乍一听责任链模式好像很高级的一样,但是相信我,其实每位天朝的同学都十分熟悉这个模式,责任链模式,就好像中国的官场制度一样,每一个级别的权利都区分的很细,举个生活中的栗子: 村委不能越级去替镇委办事情,如果村委无法解决,只能向上求助镇委 镇委不能越级去替市委办事情,如果镇委无法解决,只能向上求...
摘要:如果看不懂的话,可以在评论区中提问,我会第一时间回答你无论何时我一直都在嗯哼该文章属于编程中的那些经典套路设计模式汇总系列 在正式阅读前,我先谈谈我们该用什么姿势和心态学习设计模式: 如果你还没有过多的编程经验(泛指半年以下),我建议你把它当做小说来看,能看懂多少是多少,因为半年以下经验的程序员用到设计模式的情况只会出现在面试上,至于实际工作中?相对来说这部分不会由你负责。 如果你已...
摘要:该文章属于编程中的那些经典套路设计模式汇总系列,并且以下内容基于语言前面我们写了简单工厂模式,编程中的那些套路关于简单工厂模式,但简单工厂模式有一些不足违反开放封闭原则,所以需要设计出一套更加规范的设计模式。 该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 前面我们写了简单工厂模式,《编程中的那些套路——关于简单工厂模式》,但简单工厂模式有一些不足(...
摘要:简单工厂模式就是遵循了这一原则,它让不同职责的类各司其职。重点来了,简单工厂模式的不足但是简单工厂模式有一个不足,虽然它遵循了单一职责原则,但它违反了另一条同样很重要的原则开放封闭原则。 该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 面向对象五大原则中有一点非常重要的原则:单一职责原则。 简单工厂模式就是遵循了这一原则,它让不同职责的类各司其职。 ...
该文章属于《编程中的那些经典套路——设计模式汇总》系列,并且以下内容基于语言PHP 在设计模式中,单例模式和工厂模式)可以说是使用的最普遍的设计模式了,所以掌握此种模式尤为重要。 单例模式一般使用在资源共享和需要控制资源的情况下。 例如:购物车,回收站,数据库连接池,计数器,配置文件共享等所有项目中只需要存在一个的模块,你都可以采用单例模式。 单例模式的好处就在于当前进程只产生一个对象(或者叫...
阅读 819·2019-08-30 14:05
阅读 1711·2019-08-30 11:08
阅读 3215·2019-08-29 15:41
阅读 3590·2019-08-23 18:31
阅读 1509·2019-08-23 18:29
阅读 545·2019-08-23 14:51
阅读 2102·2019-08-23 13:53
阅读 2125·2019-08-23 13:02