php设计模式(1)-- 观察者模式 -- spl标准写法

我的设计模式系列文章
[url=http://xieye.iteye.com/blog/2404077]php设计模式(1)-- 观察者模式 -- spl标准写法[/url]
[url=http://xieye.iteye.com/blog/2404082]php设计模式(2)-- 观察者模式 -- 用trait来改进的写法[/url]
[url=http://xieye.iteye.com/blog/2404140]php设计模式(3)-- 责任链(职责链)模式[/url]
[url=http://xieye.iteye.com/blog/2404169]php设计模式(4)-- 装饰器模式[/url]


本文讲观察者模式。
部分代码来源:
https://www.ibm.com/developerworks/cn/opensource/os-cn-observerspl/

[size=x-large]概述[/size]

[b][size=large]个人的心得体会:最重要的一点,目标对象,给观察者对象发通知时,不需要对方的返回值,仅仅把通知下发就完事。[/size][/b]
这是最重要的。如果需要返回,不应该用这个设计模式。

php内建了SplSubject 和 SplObserver 接口以及一个方便的SplObjectStorage类。
SplSubject 接口 需要实现3个方法:
abstract public void attach ( SplObserver $observer ) 添加(注册)一个观察者
abstract public void detach ( SplObserver $observer ) 删除一个观察者
abstract public void notify ( void ) 当状态发生改变时,通知所有观察者

SplObserver接口需要实现一个方法
abstract public void update ( SplSubject $subject ) 在目标发生改变时接收目标发送的通知;当关注的目标调用其 notify()时被调用

[size=x-large]分析[/size]

下面构造一个需求,用户修改密码后,对其发送两种通知,一个是email通知,一个是手机短信通知。
分析需求,
1、不需要通知的返回值。
2、当目标发生状态变化时(密码修改),有多个后续处理,这时特别适合观察者。
3、监听器和目标的功能是比较分离的,不是紧密关联的。一个是发通知,一个是改数据库,这样可以借助设计模式来分解业务逻辑。
4、一般,[b]添加监听器的代码,放在客户端代码里写[/b]。

[size=x-large]代码实现[/size]

总共4个文件,
User.php, 目标对象
MobileSender.php,某个监听器对象
EmailSender.php,某个监听器对象
Client.php,客户端代码,
在这个设计模式中,客户端代码还有添加监听器。

User.php

<?php

class User implements SplSubject {

private $email;
private $username;
private $mobile;
private $password;
/**
* @var SplObjectStorage
*/
private $observers = NULL;

public function __construct($email, $username, $mobile, $password) {
$this->email = $email;
$this->username = $username;
$this->mobile = $mobile;
$this->password = $password;

$this->observers = new SplObjectStorage();
}

public function attach(SplObserver $observer) {
$this->observers->attach($observer);
}

public function detach(SplObserver $observer) {
$this->observers->detach($observer);
}

public function notify() {

foreach ($this->observers as $observer) {
$observer->update($this);
}
}

// 这是业务逻辑
public function changePassword($newPassword) {
echo __METHOD__, PHP_EOL;
$this->password = $newPassword;
$this->notify();
}

// 专门给监听器的信息,也可以省略,然后对每个字段添加get方法
public function get_observer_info(){
return [
"email" => $this->email,
"mobile" => $this->mobile,
"username" => $this->username,
"password" =>$this->password,
];
}
}


MobileSender.php

<?php
class MobileSender implements SplObserver {

public function update(SplSubject $subject) {

$userInfo = $subject->get_observer_info();
// 真正的发送短信代码略。
echo "向 手机{$userInfo['mobile']} 发送短信成功。短信内容是:你好 {$userInfo['username']}" .
"你的新密码是 {$userInfo['password']},请妥善保管", PHP_EOL;

}
}


EmailSender.php

<?php
class EmailSender implements SplObserver {

public function update(SplSubject $subject) {

$userInfo = $subject->get_observer_info();
// 真正的发送邮件代码略。
echo "向 {$userInfo['email']} 发送电子邮件成功。内容是:你好 {$userInfo['username']}" .
"你的新密码是 {$userInfo['password']},请妥善保管", PHP_EOL;

}
}


Client.php:

<?php
header('Content-Type: text/plain');

function __autoload($class_name) {
require_once "$class_name.php";
}

//定义目标对象
$user = new User('user1@domain.com', '张三', '13610002000', '123456');

// 添加监听器在客户端,
$email_sender = new EmailSender();
$mobile_sender = new MobileSender();
$user->attach($email_sender);
$user->attach($mobile_sender);

// 然后在对目标执行动作,顺序必须是先添加监听器,然后对象操作。
$user->changePassword('654321');



[size=x-large]
效果展示[/size]

在命令行,输入php Client.php,展示如下:

User::changePassword
向 user1@domain.com 发送电子邮件成功。内容是:你好 张三你的新密码是 654321,请妥善保管
向 手机13610002000 发送短信成功。短信内容是:你好 张三你的新密码是 654321,请妥善保管
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值