首页 php教程 php手册 PHP观察者设计模式项目应用案例

PHP观察者设计模式项目应用案例

Jun 06, 2016 pm 07:59 PM
php 前言 应用 文章 案例 设计模式 项目

前言:这篇文章讲的是 PHP (当然,语言无关紧要。要注重思想,并非实现工具)项目中,观察者设计模式的应用案例分析。这个案例中,我会和大家分享我对观察者的理解(概念),说说为什么要用观察者模式(应用场合),以及一些唠叨(扩展 )。喔,对了。本文

前言:这篇文章讲的是PHP(当然,语言无关紧要。要注重思想,并非实现工具)项目中,观察者设计模式的应用案例分析。这个案例中,我会和大家分享我对观察者的理解(概念),说说为什么要用观察者模式(应用场合),以及一些唠叨(扩展)。喔,对了。本文所给出的代码均为示例代码,摘自项目中的部分源码,略有改动,不可直接复用。

 

概念:

也许,你会挺过什么“钩子”、“触发器”、“事件驱动”、“回调函数”等类似这样的名词。其实,这些思想多多少少都和我要说的观察者设计模式有关。

 

如果你懂Java,你会见过这样的代码(事件监听):

this.addWindowListener(this);
登录后复制

如果你懂Javascript,你会见过这样的代码(回调函数):

$.get(“http://www.ihuxu.com”,function() {
// code...
});
登录后复制


如果,你既没有听过那些名词,也见过上述类似的代码。OK,我来说下观察者的思想。

 

很简单,无非就是当某一指定的事情发生时,程序根据预期设计好的行为予以实施。再简单点,比如有个游戏,AB两个人。如果,A跳一下,B应该做出微笑的表情;如果,A蹲一下,B应该做出哭的表情(这个例子好无厘头啊...)。这就是,观察者思想。我想你懂了,不懂我就是B了(哭笑不得)。

 

解释下两个名词,观察者(Obsever)和被观察者(Obsevable)。B是观察者,A是被观察者(解释的充分吧,自己理解)。

 

应用场合:

 

l 前景提要

这时,我刚刚加入这个团队。我们的项目是一款基于微信平台的应用(当然,也有网站端)。其中的团队成员ML已经实现好了微信端的主动推送,采用的是模板消息接口(事件源是用户在发表或者参与一些我们开发好的功能的动作)。问题来了,这时老大说,我们要采用邮件推送,由我来负责。我简单问了下ML的推送机制,居然采用的过程式的写法。这导致新功能的加入不好扩展和维护。扩展指的是我的功能不好加入原来的程序,因为没有一个标准的接口供我可用;维护是指尽管我把邮件推送的功能加进去,会导致我们的代码更显冗余致使无法更新换代。

所以,我向ML提议采用观察者设计模式,达成一致。

l 代码

既然我提到了不好扩展是因为没有统一的标准,那么我们需要提供一套标准:

 

PushObsevable.php(被观察者接口)


/**
 * 推送被(可)观察者接口
 * 
 * Created by GenialX at 2014.11.24
 * 
 */
 
Interface PushObservable {
// 注册(添加)观察者
Public function addObserver(PushObserver $pObserver);
// 移除观察者
Public function removeObserver(PushObserver $pObserver);
// 通知观察者
Public function notify();
}
登录后复制


 

PushObserver(观察者接口)

 

/**
 * 推送观察者接口
 * 
 * Created by GenialX at 2014.11.24
 * 
 */
 
Interface PushObserver {
// 返回名称
Public function getName();
// 更新
Public function update();
 
}
登录后复制


有了标准的接口,但是并不希望直接声明类直接实现这些接口,因为这不利实现,导致在每声明一个类继承这个接口时都需要重新写一遍一样的实现。所以,继而分别写了两个抽象类继承并实现了这些接口中的成员方法。


AbstractPushObservable(被观察者抽象类)

/**
 * 被观察者抽象类
 * 
 * Created by GenialX at 2014.11.24
 * 
 */
require_once 'PushObservable.php';
Abstract Class AbstractPushObservable Implements PushObservable {
	
	Private $_observers = array(); // 观察者容器
	
	// 注册(添加)观察者
	Public function addObserver(PushObserver $pObserver) {
		if( ! isset( $this->_observers[ $pObserver->getName() ] ) ) {
			$this->_observers[ $pObserver->getName() ] = & $pObserver;
			return TRUE;
		}
		return FALSE;
	}
	
	// 移除观察者
	Public function removeObserver(PushObserver $pObserver) {
		if( isset( $this->_observers[ $pObserver->getName() ] ) ) {
			$this->_observers[ $pObserver->getName() ] = NULL;
			unset( $this->_observers[ $pObserver->getName() ] );
			return TRUE;
		}
		return FALSE;
	}
	
	// 获取观察者
	// $name 唯一标识 可取InterfacePush 常量
	Public function getObserver($name) {
		if( isset( $this->_observers[ $name ] ) ) {
			return $this->_observers[ $name ] ;
		}
		return FALSE;
	}
	
	// 通知观察者
	Public function notify() {
		foreach ( $this->_observers as $observer ) {
			$observer->update();
		}
	}
	
}
登录后复制


AbstractPushObserver(观察者抽象类)

/**
 * 观察者抽象类
 * 
 * Created by GenialX at 2014.11.24
 * 
 */

require_once 'PushObserver.php';
Abstract Class AbstractPushObserver Implements PushObserver{
	
	Private $_name; // 名称(唯一标志)
	
	Public function __construct($name = NULL) {
		if(is_null($name)) {
			$this->_name = 'AbstractPushObserver' . rand(1000,9999);
		} else {
			$this->_name = $name;
		}
	}
	
	// 返回名称
	Public function getName() {
		return $this->_name;
	}
	
	// 更新
	Public function update() {
		// 重写方法...
	}
}
登录后复制


 

有了抽象类,这时是不是可以直接声明类继承这些抽象类了呢?是的。但是,在我们的项目中并没有采用直接声明类继承这些抽象类。因为针对,微信的模板消息推送和邮件推送仍有一些公用的实现。所以,分别写了公用的实现类。

CommonPushObservable(公用推送被观察者类)

 

/**
 * 公用推送被观察者类
 * 
 * Created by GenialX at 2014.11.24
 * 
 */
require_once 'AbstractPushObservable.php';
Class CommonPushObservable Extends AbstractPushObservable {
	
	Public function __construct() {}
	
}
登录后复制


CommonPushObserver(公用推送观察者类)

 

/**
 * 公用推送观察者类
 * 
 * Created by GenialX at 2014.11.25
 * 
 */
require_once 'AbstractPushObserver.php';
class CommonPushObserver extends AbstractPushObserver {
	private static $weixinUsers = array (); // 符合推送的微信用户信息
	private static $renrenUsers = array (); // 符合推送的人人用户信息
	public static $CI;
	Public function __construct($name = NULL) {
		parent::__construct ( $name );
		CommonPushObserver::$CI = & get_instance ();
		CommonPushObserver::$CI->load->library ( 'distance' );
	}
	
	/**根据地理位置获取符合推送条件的用户信息
	 *
	 * @param float $lon        	
	 * @param float $lat        	
	 * @param string $fromUser        	
	 *
	 */
	Public Static function getUsers($lon, $lat, $fromUser) {
		// ... 
	}
	

登录后复制

 

这时,已经设计好了推送机制的标准。只要针对这个标准去实现不同的功能即可。这样,不必担心扩展和维护的问题。因为,有了标准。

 

先看下调用代码(就这么优雅):


$CPO = new CommonPushObservable(); // 实例化被观察者
  
$EP = new EmailPush(EmailPush::PUSH_EMAIL_OBJECT); // 实例化观察者(邮件推送观察者类,下文有代码)
$WP = new WechatPush(WechatPush::PUSH_EMAIL_OBJECT); // 实例化观察者(微信消息模板观察者类)
$EP->setPushType($EP::PUSH_TYPE_WISH_LIST); // 设置推送类型
$EP->setPushType($WP::PUSH_TYPE_WISH_LIST); // 设置推送类型
$EP->id('12')->email('genialx@163.com')->text('Hello World!'); // 设置消息体
$EP->openid(‘openid’)->text(‘Hello World!’); // 设置消息体
$EP->getUsers($lon, $lat, $fromUser); // 获取用户
$CPO->addObserver($EP); // 注册观察者
$CPO->addObserver($WP); // 注册观察者

$CPO->notify(); // 通知观察者 推送微信消息和邮件消息
登录后复制

 扩展:


1、推送类型和消息体的设置重复,那么你是否会想到封装?

2PUSH_TYPE_WISH_LIST类似常量的存在是不是更好?

 

答案是肯定的!

 

参考文章:PHP观察者模式 http://www.ihuxu.com/php-design-mode-observer.html

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CakePHP 项目配置 CakePHP 项目配置 Sep 10, 2024 pm 05:25 PM

在本章中,我们将了解CakePHP中的环境变量、常规配置、数据库配置和电子邮件配置。

适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 适用于 Ubuntu 和 Debian 的 PHP 8.4 安装和升级指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 带来了多项新功能、安全性改进和性能改进,同时弃用和删除了大量功能。 本指南介绍了如何在 Ubuntu、Debian 或其衍生版本上安装 PHP 8.4 或升级到 PHP 8.4

CakePHP 日期和时间 CakePHP 日期和时间 Sep 10, 2024 pm 05:27 PM

为了在 cakephp4 中处理日期和时间,我们将使用可用的 FrozenTime 类。

CakePHP 文件上传 CakePHP 文件上传 Sep 10, 2024 pm 05:27 PM

为了进行文件上传,我们将使用表单助手。这是文件上传的示例。

CakePHP 路由 CakePHP 路由 Sep 10, 2024 pm 05:25 PM

在本章中,我们将学习以下与路由相关的主题?

讨论 CakePHP 讨论 CakePHP Sep 10, 2024 pm 05:28 PM

CakePHP 是 PHP 的开源框架。它的目的是使应用程序的开发、部署和维护变得更加容易。 CakePHP 基于类似 MVC 的架构,功能强大且易于掌握。模型、视图和控制器 gu

如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 如何设置 Visual Studio Code (VS Code) 进行 PHP 开发 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也称为 VS Code,是一个免费的源代码编辑器 - 或集成开发环境 (IDE) - 可用于所有主要操作系统。 VS Code 拥有针对多种编程语言的大量扩展,可以轻松编写

CakePHP 创建验证器 CakePHP 创建验证器 Sep 10, 2024 pm 05:26 PM

可以通过在控制器中添加以下两行来创建验证器。

See all articles