当前位置: 首页 > 后端技术 > PHP

Laravel核心解读--观察者模式

时间:2023-03-30 01:07:21 PHP

观察者模式Laravel的Event事件系统提供了一个简单的观察者模式实现,可以订阅和监听应用中发生的各种事件,在PHP的标准库(SPL)中甚至提供了三个接口SplSubject,SplObserver,和SplObjectStorage让开发者更容易实现观察者模式,但是我还是想脱离SPL提供的接口和具体的编程语言来谈谈如何通过面向对象编程来实现观察者模式,该示例是PHP代码,但在其他面向对象语言中的实现是相同的。模式定义观察者模式(ObserverPattern):定义了对象之间一对多的依赖关系,这样每当一个对象状态发生变化时,其相关的依赖对象就会得到通知并自动更新。观察者模式也称为发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听(Source/Listener)模式或从属(Dependents)模式。观察者模式的核心在于Subject和Observer接口。Subject(主题目标)包含一个给定的状态。观察者“订阅”主题并通知观察者主题的当前状态。每次给定状态发生变化时,所有观察者都会收到通知。变化的对象称为观察目标,通知的对象称为观察者。一个观察目标可以对应多个观察者,这些观察者之间没有关联。可以根据需要添加和删除观察者,使系统更易于扩展。模式结构描述Subject对象抽象类ConcreteSubject具体对象Observer观察者抽象类ConcreteObserver具体Observer应用实例例如设置用户状态(subject)后发送当前状态描述信息到用户邮箱和手机,我们可以使用两个观察者订阅用户的状态。一旦设置了状态,主题将通知已订阅状态更改的观察者。在两个观察者中,我们可以分别实现发送邮件信息和短信信息的功能。抽象类Subject{protected$stateNow;保护$observers=[];publicfunctionattach(Observer$observer){array_push($this->observers,$observer);}publicfunctiondetach(Observer$ob){$pos=0;foreach($this->observersas$viewer){if($viewer==$ob){array_splice($this->observers,$pos,1);}}$pos++;}}publicfunctionnotify(){foreach($this->observersas$viewer){$viewer->update($this);}}}在抽象类中,attachdetach和notify都是具体的方法。这些方法只能通过继承来使用,并且会被的子类使用的Subject使用。具体目标类classConcreteSubjectextendsSubject{publicfunctionsetState($state){$this->stateNow=$state;$this->通知();}publicfunctiongetState(){return$this->stateNow;}}abstractionObserverabstractclassObserver{abstractpublicfunctionupdate(Subject$subject);在抽象观察者中,抽象方法更新等待子类为其提供具体实现。具体观察者类ConcreteObserverDTextendsObserver{private$currentState;publicfunctionupdate(Subject$subject){$this->currentState=$subject->getState();}echo''.$this->currentState.'

';}}classConcreteObserverPhoneextendsObserver{private$currentState;publicfunctionupdate(Subject$subject){$this->currentState=$subject->getState();}echo''.$this->currentState.'
';}}在例子中,为了方便理解,我们只是设置了不同的Content样式,在实际应用中,其实可以调用email和SMS服务来发送信息。使用观察者模式classClient{publicfunction__construct(){$sub=newConcreteSubject();$obDT=newConcreteObserverDT();$obPhone=newConcreteObserverPhone();$sub->attach($obDT);$sub->attach($obPhone);$sub->setState('你好世界');}}$worker=newClient();当使用观察者模式时,一个对象的变化会引起一个或多个其他对象的变化,而不知道有多少对象会发生变化,这样可以降低对象之间的耦合度。一个对象必须在不知道这些对象是谁的情况下通知其他对象。基于事件触发机制对复杂逻辑进行解耦时,从整个逻辑的不同关键点抽象出不同的事件。主进程只需要关心核心逻辑并能正确触发事件(Subject),其余相关功能由观察者实现。或者打电话给订户去做。总结观察者模式定义了一对多的依赖关系,允许多个观察者对象同时监视一个目标对象。当目标对象的状态发生变化时,会通知所有的观察者对象,使其自动更新。该模式包含四个角色:目标也称为主体,指要观察的对象;具体目标是目标类的子类,通常它包含经常变化的数据,当它的状态发生变化时,它会向它的每个观察者发送通知;观察者会响应被观察目标的变化;在特定观察者中维护对特定目标对象的引用,该引用存储特定观察者的相关状态,这些状态需要与特定目标的状态保持一致。观察者模式的主要优点是可以实现表现层和数据逻辑层的分离,并在观察目标和观察者之间建立抽象耦合,支持广播通信;它的主要缺点是如果一个观察目标对象有很多直接和间接的观察者,通知所有观察者会花费很多时间,如果观察者和观察目标之间存在循环依赖,观察目标就会触发它们之间的循环调用,这可能会导致系统崩溃。本文已收录在Laravel源码学习系列文章中,欢迎访问阅读。