SplSubject代表着被观察的对象,其结构:
interface SplSubject{
//添加(注册)一个观察者
public function attach(SplObserver $observer);
//删除一个观察者
public function detach(SplObserver $observer);
//当状态发生改变时,通知所有观察者
public function notify();
}
SplSubject 接口中的方法:
方法声明 | 描述 |
---|---|
abstract public void attach ( SplObserver $observer ) | 添加(注册)一个观察者 |
abstract public void detach ( SplObserver $observer ) | 删除一个观察者 |
abstract public void notify ( void ) | 当状态发生改变时,通知所有观察者 |
SplObserver 代表着充当观察者的对象,其结构:
interface SplObserver{
//在目标发生改变时接收目标发送的通知;当关注的目标调用其notify()时被调用
public function update(SplSubject $subject);
}
SplObserver 中的方法:
方法声明 | 描述 |
---|---|
abstract public void update ( SplSubject $subject ) | 在目标发生改变时接收目标发送的通知;当关注的目标调用其notify()时被调用 |
<说明>
该设计模式的核心思想是, SplSubject
维护了一个特定的状态,在其状态改变时会调用 notify() 方法,一旦这个方法被调用,任何先前通过 attach() 方法注册上来的 SplObserver
对象都会以调用其 update() 方法的方式被更新。
为什么使用 SplObjectStorage 类?
SplObjectStorage
类实现了以对象为键的映射(map)或对象的集合(如果忽略作为键的对象所对应的数据)这种数据结构。这个类的实例很像一个数组,但是它所存放的对象都是唯一的。这个特点就为快速实现 Observer 设计模式贡献了不少力量,因为我们不希望同一个观察者被注册多次。该类的另一个特点是,可以直接从中删除指定的对象,而不需要遍历或搜索整个集合。
SplObjectStorage::attach() 方法的部分源代码:
function attach($obj, $inf = NULL)
{
if (is_object($obj) && !$this->contains($obj))
{
$this->storage[] = array($obj, $inf);
}
}
SplObjectStorage类的实例之所以能够只存储唯一的对象,是因为其 SplObjectStorage::attach()方法的实现中先判断了指定的对象是否已经被存储:
<?php
/**
* this is the base class
*/
class Base
{
function __construct()
{
echo 'base Class';
}
}
class MyObserver implements SplObserver
{
public function update(SplSubject $subject)
{
echo "MyObserver2 updated\n";
print_r($this->getUserInfo($subject));
}
public function getUserInfo($subject)
{
return $subject->getUserInfo();
}
}
class User extends Base implements SplSubject {
private $_email;
private $_username;
private $_mobile;
private $_password;
private $_userInfo;
/**
* @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 setUserInfo()
{
$userInfo = array(
'username' => $this->_username,
'password' => $this->_password,
'email' => $this->_email,
'mobile' => $this->_mobile,
);
$this->_userInfo = $userInfo;
}
public function getUserInfo()
{
return $this->_userInfo;
}
public function create() {
echo __METHOD__, PHP_EOL;
$this->setUserInfo();
$this->notify();
}
public function changePassword($newPassword) {
echo __METHOD__, PHP_EOL;
$this->_password = $newPassword;
$this->setUserInfo();
$this->notify();
}
public function resetPassword() {
echo __METHOD__, PHP_EOL;
$this->_password = mt_rand(100000, 999999);
$this->setUserInfo();
$this->notify();
}
}
class EmailSender implements SplObserver {
public function update(SplSubject $subject) {
$userInfo = $subject->getUserInfo(); //调用被观察者的函数
echo "向 {$userInfo['email']} 发送电子邮件成功。内容是:你好 {$userInfo['username']}" .
"你的新密码是 {$userInfo['password']},请妥善保管", PHP_EOL;
}
}
class MobileSender implements SplObserver {
public function update(SplSubject $subject) {
$userInfo = $subject->getUserInfo();
echo "向 {$userInfo['email']} 发送短信成功。内容是:你好 {$userInfo['username']},你的新密码是 {$userInfo['password']},请妥善保管", PHP_EOL;
}
}
测试用例Test Case:
<代码>
class testDriver
{
public function run()
{
//observer
$observer = new MyObserver();
$subject = new User('user@domain.com', '张三', '13610002000', '123456');
$subject->attach($observer);
$subject->notify();
$email_sender = new EmailSender();
$mobile_sender = new MobileSender();
$user = new User('user@domain.com', '张三', '13610002000', '123456');
// 创建用户时通过 Email 和手机短信通知用户
$user->attach($email_sender);
$user->attach($mobile_sender);
$user->create($user);
$user->resetPassword($user);
echo PHP_EOL;
}
}
$test = new testDriver();
$test->run();
搜索
标签
study
ab
amap
apache
apahe
awk
aws
bat
centos
CFS
chrome
cmd
cnpm
composer
consul
crontab
css
curl
cygwin
devops
di
docker
docker,docker-compose
ethereum
excel
fiddler
fluentd
framework
front-end
git
gitgui
github
glide
go
golang
gorm
grafana
gzip
ioc
item2
iterm2
javascript
jenkins
jsonp
kafka
laradock
laravel
larval
linux
liunux
log
mac
mac, wi-fi
macos
magento
mariaDB
minikube
mongoDB
msp
mysql
netbeans
nginx
nodejs
nohup
npm
nsq
oracle
php
php-fpm
php7
phpstorm
php扩展
Protobuf
python
redis
scp
server
shell
soap
socket
socket5
sql
sre
ssdb
ssh
ssl
study
sublime
swift
system
td-agent
uml
v2ray
vagrant
vagrnat
vim
vpn
vue
vue.js
webpack
webrtc
websocket
webtatic
windows
windows7
word
wps
xdebug
yarn
yii2
yum
zookeeper
世界国家
互联网
以太坊
分类
前端
小程序
打印机
排序算法
搞笑
权限
粤语
缓存
网络
虚拟机
视频
设计模式
项目管理
热门文章
友情链接