php设计模式入门-观察者模式
来源:互联网 发布:淘宝联盟推广位爱分享 编辑:程序博客网 时间:2024/05/16 15:04
场景:一个气象站点,当温度、湿度或气压发生改变时都要像订阅了该气象服务的用户推送提醒,假设用户拥有三种电子产品:mac、iphone和apple watch。
第一版的设计代码如下:
WeatherData.php
<?php/** * 气象站类,用于提供气象数据,数据变化时及时推送至用户的设备 * * @author ben * */class WeatherData{/** * 气温 * @var string */private $_temperature;/** * 气压 * @var string */private $_pressure;/** * 湿度 * @var string */private $_humidity;/** * 用户设备之mac * @var object */private $_mac;/** * 用户设备之iphone * @var object */private $_iphone;/** * 用户设备之watch(壕啊,咱们做朋友吧。。。) * @var object */private $_iwatch;/** * 初始化用户设备 * @param object $mac * @param object $iphone * @param object $iwatch */public function __construct($mac, $iphone, $iwatch){$this->_mac = $mac;$this->_iphone = $iphone;$this->_iwatch = $iwatch;}/** * 当数据变更时向用户推送即时数据 */public function dataChanged(){$this->_temperature = $this->getTemperature();$this->_humidity = $this->getHumidity();$this->_pressure = $this->getPressure();$this->_mac->update($this->_humidity, $this->_temperature, $this->_pressure);$this->_iphone->update($this->_humidity, $this->_temperature, $this->_pressure);$this->_iwatch->update($this->_humidity, $this->_temperature, $this->_pressure);}}
代码的坏味道:
气象站类WeatherData与用户的设备类mac、iphone、iwatch类之间存在着强耦合关系,而真实的场景中用户可能随时会取消业务,或者为新的电子产品订阅该业务,这就意味着我们今后将会频繁的修改这个文件中的代码。
下面我们来看看观察者模式是怎么为我们解决这个难题的。
要理解观察者模式,可以结合真实的案例,比如说订阅报纸,仔细想想在这样的场景中存在哪几种元素:
1、报纸的发布者;
2、报纸的订阅者;
发布者与订阅者组成了观察者的两个基本要素。具体用uml类图描述如下:
具体的实现代码:
Subject.php
<?phpabstract class Subject{protected $observers;public function addObserver($key, Equipment $observer){$this->observers[$key] = $observer;}public function removeObserver($key){if(isset($this->observers[$key])){unset($this->observers[$key]);}}abstract function notify();// foreach ($this->observer as $observer){// $observer->update();// }}
Equipment.php
<?phpabstract class Equipment{abstract function update($temperature, $pressure, $humidity);abstract function display();}WeatherData.php
<?phprequire_once 'Subject.php';class WeatherData extends Subject{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Subject::notify() */public function notify() {foreach ($this->observers as $observer){$observer->update($this->_temperature, $this->_pressure, $this->_humidity);}}public function dataChange($temperature, $pressure, $humidity){$this->_temperature = $temperature;$this->_pressure = $pressure;$this->_humidity = $humidity;$this->notify();}}
Mac.php
<?phprequire_once 'Equipment.php';class Mac extends Equipment{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update($temperature, $pressure, $humidity) {// TODO Auto-generated method stub$this->_temperature = $temperature;$this->_pressure = $pressure;$this->_humidity = $humidity;$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Mac client<br />";}}
Iwatch.php
<?phprequire_once 'Equipment.php';class Iwatch extends Equipment{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update($temperature, $pressure, $humidity) {// TODO: Auto-generated method stub$this->_temperature = $temperature;$this->_pressure = $pressure;$this->_humidity = $humidity;$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Iwatch client<br />";}}Iphone.php
<?phprequire_once 'Equipment.php';class Iphone extends Equipment{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update($temperature, $pressure, $humidity) {// TODO Auto-generated method stub$this->_temperature = $temperature;$this->_pressure = $pressure;$this->_humidity = $humidity;$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Iphone client<br />";}}index.php
<?phprequire_once 'WeatherData.php';require_once 'Iwatch.php';require_once 'Iphone.php';require_once 'Mac.php';$subject = new WeatherData();$observer1 = new Iwatch();$observer2 = new Iphone();$observer3 = new Mac();$subject->addObserver('Iwatch', $observer1);$subject->addObserver('Iphone', $observer2);$subject->addObserver('Mac', $observer3);$subject->dataChange('38摄氏度', '气压好高啊', '很湿润');
运行结果是:
Current conditions:temperature:38摄氏度;pressure:气压好高啊;humidity:很湿润; --From Iwatch clientCurrent conditions:temperature:38摄氏度;pressure:气压好高啊;humidity:很湿润; --From Iphone clientCurrent conditions:temperature:38摄氏度;pressure:气压好高啊;humidity:很湿润; --From Mac client
当然php已经帮我们准备好了两个接口,我们没有必要重造轮子,这两个接口分别是SplObserver和SplSubject,关于这两个接口的定义,可以查看以下官方文档:
SplObserver:http://php.net/manual/zh/class.splobserver.php
SplSubject:http://php.net/manual/zh/class.splsubject.php
使用这两个接口之后我们进一步修改后的代码清单如下:
index.php
<?phprequire_once 'WeatherData.php';require_once 'Iwatch.php';require_once 'Iphone.php';require_once 'Mac.php';$subject = new WeatherData();$observer1 = new Iwatch();$observer2 = new Iphone();$observer3 = new Mac();$subject->attach($observer1);$subject->attach($observer2);$subject->attach($observer3);$subject->dataChange('38摄氏度', '气压好高啊', '很湿润');
<?phpclass Iphone implements SplObserver{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update(SplSubject $subject) {// TODO Auto-generated method stub$this->_temperature = $subject->getTemperature();$this->_pressure = $subject->getPressure();$this->_humidity = $subject->getHumidity();$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Iphone client<br />";}}
<?phpclass Iwatch implements SplObserver{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update(SplSubject $subject) {// TODO Auto-generated method stub$this->_temperature = $subject->getTemperature();$this->_pressure = $subject->getPressure();$this->_humidity = $subject->getHumidity();$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Iwatch client<br />";}}
Mac.php
<?phpclass Mac implements SplObserver{private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Equipment::update() */public function update(SplSubject $subject) {// TODO Auto-generated method stub$this->_temperature = $subject->getTemperature();$this->_pressure = $subject->getPressure();$this->_humidity = $subject->getHumidity();$this->display();}/* (non-PHPdoc) * @see Equipment::display() */public function display() {// TODO Auto-generated method stubecho "Current conditions:<br />temperature:$this->_temperature;<br />pressure:$this->_pressure;<br />humidity:$this->_humidity;<br /> --From Mac client<br />";}}WeatherData.php
<?phpclass WeatherData implements SplSubject{protected $observers;private $_temperature;private $_pressure;private $_humidity;/* (non-PHPdoc) * @see Subject::notify() */public function notify() {foreach ($this->observers as $observer){$observer->update($this);}}public function dataChange($temperature, $pressure, $humidity){$this->_temperature = $temperature;$this->_pressure = $pressure;$this->_humidity = $humidity;$this->notify();}public function getTemperature(){return $this->_temperature;}public function getPressure(){return $this->_pressure;}public function getHumidity(){return $this->_humidity;}/* (non-PHPdoc) * @see SplSubject::attach() */public function attach(SplObserver $observer) {// TODO Auto-generated method stub$this->observers[] = $observer;}/* (non-PHPdoc) * @see SplSubject::detach() */public function detach(SplObserver $observer) {// TODO Auto-generated method stub$key = array_search($observer, $this->observers, true);if($key){unset($this->observers[$key]);}}}
0 0
- php设计模式入门-观察者模式
- php 观察者设计模式
- 设计模式入门-观察者模式
- 设计模式入门--观察者模式
- PHP设计模式:观察者模式
- php设计模式-观察者模式
- [php] 设计模式 观察者模式
- PHP设计模式-观察者模式
- 设计模式入门学习 观察者模式
- 设计模式入门之观察者模式Observer
- 设计模式入门-观察者模式(二)
- Php设计模式之观察者模式
- PHP设计模式系列 - 观察者模式
- 设计模式php实例:观察者模式
- PHP 设计模式之观察者模式
- PHP 设计模式之观察者模式
- php设计模式之观察者模式
- PHP设计模式——观察者模式
- 对canvas的translate()方法的理解
- 自己出的题 squee_spoon and his Cube III
- .net中对象占用资源的回收
- 单例模式的实现(ARC与非ARC)
- Eclipse提交代码错误:rejected –non-fast-forward
- php设计模式入门-观察者模式
- Android ActionBar应用实战,高仿微信主界面的设计
- STM32在MDK5下建立工程文件步骤分析
- 简单工厂模式(二)
- 列选取原则
- Please login to the following domain:This is We Cloud Technology Group,please enter your passcode
- T001-UT001-0018
- 辨别系统是大端or小端字节序---通过联合体
- 内存管理